package cit.PureATN; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Shape; import java.awt.geom.GeneralPath; import java.awt.geom.Point2D; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.Serializable; import java.lang.reflect.Field; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Hashtable; import java.util.NoSuchElementException; import java.util.StringTokenizer; import java.util.Vector; import org.piccolo2d.PNode; import org.piccolo2d.activities.PActivity; import org.piccolo2d.nodes.PPath; import org.piccolo2d.util.PBounds; /** * 生徒の筆記(1ストローク)モデル * @author miuramo * */ public class ShortStroke extends PPPath implements Serializable, Runnable { private static final long serialVersionUID = 5928762332664417016L; //TODO: 筆記解析をするならtrue public transient static boolean doAssess = false; public float[] sx; public float[] sy; // public short[] penpress; public float width; public int color; public int penid;//ペンのID // public int paperid;//シートのID public long time; // public int sbackid; public transient long id; public transient ArrayList<Point2D> tempPts; public transient PNode ink; public transient Point2D startp; public transient Shape full; // transient Event_onSS event_onss = null; public String toCsv(){ SimpleDateFormat sdf = new SimpleDateFormat("\"yyyy/MM/dd HH:mm:ss\""); StringBuffer sb = new StringBuffer(); sb.append(penid); sb.append(","); // sb.append(paperid); // sb.append(","); sb.append(String.valueOf(time)); sb.append(","); sb.append(sdf.format(time)); sb.append(","); sb.append(sx.length); sb.append(","); for(int i=0;i<sx.length;i++){ sb.append(sx[i]); sb.append(","); sb.append(sy[i]); sb.append(","); } String s = sb.toString(); return s.substring(0,s.length()-1); } public transient int interval; public transient Thread playthread; public transient boolean playing; //for playing public transient ArrayList<Shape> shapel; public transient PBounds bounds; static Hashtable<String, BasicStroke> penStrokeHash; static Hashtable<Integer, Color> colorHash; static { penStrokeHash = new Hashtable<String, BasicStroke>(); colorHash = new Hashtable<Integer, Color>(); } public static BasicStroke getCachedBasicStroke(float f){ //f=太さ if (penStrokeHash.containsKey(java.lang.Float.valueOf(f).toString())){ return penStrokeHash.get(java.lang.Float.valueOf(f).toString()); } else { BasicStroke bs = new BasicStroke( f/2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 90.0f); penStrokeHash.put( java.lang.Float.valueOf(f).toString(), bs); return bs; } } public static Color getColor(int f){ if (colorHash.containsKey(f)){ return colorHash.get(f); } else { Color opaqueC = new Color(f); Color cl = new Color(opaqueC.getRed(), opaqueC.getGreen(), opaqueC.getBlue(), 245); //TODO:ここで筆記の透明度を設定.以前は95 colorHash.put(f, cl); return cl; } } // 新規作成 public ShortStroke() { this(0, new Color(0,0,90), 3, new Date().getTime()); } public ShortStroke(int _penid, Color _color, int _width, long _time){ penid = _penid; color = _color.getRGB(); this.setStrokePaint(_color); width = _width; setStroke(getCachedBasicStroke(width)); time = _time; setTransparency(0.7f); playing = false; } // startDragのまえに、layer.addChildしておく public void startDrag_on_draw(double px, double py){ tempPts = new ArrayList<Point2D>(); this.moveTo(px,py); } public void drag_on_draw(double px, double py){ tempPts.add(new Point2D.Double(px,py)); this.lineTo(px,py); } public void endDrag_on_draw(){ applyTempPtsToAry(); } public void applyTempPtsToAry(){ sx = new float[tempPts.size()]; sy = new float[tempPts.size()]; // penpress = new short[tempPts.size()]; for(int i=0;i<tempPts.size();i++){ sx[i] = (float)tempPts.get(i).getX(); sy[i] = (float)tempPts.get(i).getY(); // penpress[i] = 127; } } public Color getColor(){ return ShortStroke.getColor(color); } public void setColor(Color c){ setStrokePaint(c); //元のデータも書き換える color = c.getRGB(); } public void animateToFlushColor(Color flushcolor, long duration, long startwait){ PActivity a1 = this.animateToColor(flushcolor, duration); PActivity a2 = this.animateToColor(getColor(), duration); a1.setStartTime(System.currentTimeMillis()+startwait); a2.startAfter(a1); } public Point2D getPenPoint(int pos) { return new Point2D.Float(sx[pos], sy[pos]); } public Point2D getFirstPoint() { return new Point2D.Float(sx[0], sy[0]); } public Point2D getLastPoint() { return new Point2D.Float(sx[sx.length - 1], sy[sy.length - 1]); } public synchronized void run() { playing = true; reset(); ink.addChild(this); moveTo(sx[0], sy[0]); for (int i = 1; i < sx.length; i++) { lineTo(sx[i], sy[i]); ink.repaintFrom(getBoundsReference(), this); try { Thread.sleep(interval); } catch (InterruptedException e) { e.printStackTrace(); } if (!playing) return; } // removeFromParent(); // ink.addChild(this); // ink.repaintFrom(getBoundsReference(), this); // if (SnailServer.server.recognizeCB.isSelected()) // note.recognize(this); // note.student.afterAddDBStroke(note, this); stop(); } public void suspend() { synchronized (playthread) { try { playthread.wait(); // プロセスを休止する } catch (InterruptedException e) { } } } public synchronized void resume() { playthread.notify(); } public void stop() { if (playing) playing = false; if (playthread != null) playthread = null; // ink.repaint(); } public synchronized PPath genStroke(String protocol, float inkscale) { return genStroke_old(protocol, inkscale); // return genStroke_besier(protocol); } // public PPath getStroke(){ // if (stroke!=null) return stroke; // else return rebuildStroke(); // } public synchronized PPath genStroke_besier(String protocol, float inkscale) { StringTokenizer st = new StringTokenizer(protocol); Vector<double[]> v = new Vector<double[]>(); int c = st.countTokens(); int p = 0; sx = new float[c / 2]; sy = new float[c / 2]; float tsx = (float) (Integer.parseInt(st.nextToken(), 36) * inkscale); float tsy = (float) (Integer.parseInt(st.nextToken(), 36) * inkscale); float ttx, tty; // previous values; sx[p] = tsx; sy[p] = tsy; // System.out.println("tsx: "+ tsx + " tsy: "+tsy); double[] t = new double[2]; t[0] = tsx; t[1] = tsy; v.add(t); ttx = tsx; tty = tsy; while (st.hasMoreElements()) { p++; float x = (float) (Integer.parseInt(st.nextToken(), 36) * inkscale); float y = (float) (Integer.parseInt(st.nextToken(), 36) * inkscale); sx[p] = x; sy[p] = y; if (x != ttx && y != tty) { double[] tt = new double[2]; tt[0] = x; tt[1] = y; v.add(tt); } } // FitCurves fc = new FitCurves(); // try { // fc.getBezier(v, 4.0); // } catch (ArrayIndexOutOfBoundsException aioobe) { // genStroke_old(protocol, inkscale); // } return this; } public synchronized PPath genStroke_old(String protocol, float inkscale) { try { StringTokenizer st = new StringTokenizer(protocol); time = new Date().getTime(); // System.out.println(time); int c = st.countTokens(); int p = 0; sx = new float[c / 2]; sy = new float[c / 2]; // stroke = new MyPPath(this); reset(); float tsx = (float) (Integer.parseInt(st.nextToken(), 36) * inkscale); float tsy = (float) (Integer.parseInt(st.nextToken(), 36) * inkscale); moveTo((float) tsx, (float) tsy); sx[p] = tsx; sy[p] = tsy; while (st.hasMoreElements()) { p++; float x = (float) (Integer.parseInt(st.nextToken(), 36) * inkscale); float y = (float) (Integer.parseInt(st.nextToken(), 36) * inkscale); lineTo((float) x, (float) y); sx[p] = x; sy[p] = y; } return this; } catch (NoSuchElementException ex) { System.out.println(ex.toString()); return null; } } public synchronized PPath rebuildStroke_old() { // stroke = new MyPPath(this); reset(); if (sx.length == 0 || sy.length == 0) { System.out.println("長さ0のストロークデータ " + time); return this; } moveTo((float) sx[0], (float) sy[0]); for (int i = 0; i < sx.length; i++) { lineTo((float) sx[i], (float) sy[i]); } full = new GeneralPath(this.getPathReference()); // 最後までの筆記を記録 // removeAllChildren(); // for(int i=0;i<sx.length;i++){ // PPath a = PPath.createEllipse(sx[i]-0.3f, sy[i]-0.3f, 0.3f, 0.3f); // a.setPaint(getColor(3000000)); // a.setStrokePaint(getColor(3000000)); // addChild(a); // } return this; // return this; } public void calcMetrics(){ if (dist < 0){ //初期値は-1なので。はじめてかどうかのチェック lengthInPixel(); maxspeedInPixel(); varspeedInPixel(); angle(); ramer(); log(); } } // public void exportBySieve(){ //TODO: // calcMetrics(); // FileReadWriter.buffer.add(var_ramer+","+num_choten+","+num_choten2+","+ramer+","+penid+","+time+","+ppd+","+pts+","+dist); // /* // * FileReadWriter.buffer.add(id+","+time+","+sbackid+","+penid+","+paperid+","+ // sx.length+","+length+","+avgspeed+","+varspeed+","+varspeed2+","+maxspeed+","+timediff+","+timed+","+ // num_choten+","+num_choten2+","+numrammer);//研究用 // */ // // FileReadWriter.buffer.add(timed+","+num_choten+","+num_choten2+","+numrammer+","+ // // varspeed+","+varspeed2+","+avgspeed+","+avgspeed2);//分析1用 // // FileReadWriter.buffer.add(num_choten+","+varspeed+","+avgspeed);//分析2-1用 // // FileReadWriter.buffer.add(num_choten2+","+varspeed2+","+avgspeed2);//分析2-2用 // // FileReadWriter.buffer.add(numrammer+","+varspeed+","+avgspeed);//分析2-3用 // // FileReadWriter.buffer.add(numrammer+","+varspeed2+","+avgspeed2);//分析2-4用 // // // //System.out.println(penid+" "+paperid+" count "+sx.length+" len "+length+" avg "+avgspeed+" var "+varspeed+" max "+maxspeed+" td "+timediff); // //太さと色を設定 // } public void exportBySieveAverage(){ //TODO: calcMetrics(); /* * FileReadWriter.buffer.add(id+","+time+","+sbackid+","+penid+","+paperid+","+ sx.length+","+length+","+avgspeed+","+varspeed+","+varspeed2+","+maxspeed+","+timediff+","+timed+","+ num_choten+","+num_choten2+","+numrammer);//研究用 */ // FileReadWriter.buffer.add(timed+","+num_choten+","+num_choten2+","+numrammer+","+ // varspeed+","+varspeed2+","+avgspeed+","+avgspeed2);//分析1用 // FileReadWriter.buffer.add(num_choten+","+varspeed+","+avgspeed);//分析2-1用 // FileReadWriter.buffer.add(num_choten2+","+varspeed2+","+avgspeed2);//分析2-2用 // FileReadWriter.buffer.add(numrammer+","+varspeed+","+avgspeed);//分析2-3用 // FileReadWriter.buffer.add(numrammer+","+varspeed2+","+avgspeed2);//分析2-4用 // //System.out.println(penid+" "+paperid+" count "+sx.length+" len "+length+" avg "+avgspeed+" var "+varspeed+" max "+maxspeed+" td "+timediff); //太さと色を設定 } public synchronized PPath rebuildStroke() { setStroke(getCachedBasicStroke(width)); setStrokePaint(getColor(color)); // float h = (float)(avgspeed/3); // if (h>1.0) h=1.0f; // float b = (float)(Math.log(varspeed+0.01)+0.2); // if (b>1.0) b=1.0f; // int hh = (int)(h*205)+50; // if (hh>255) hh=255; // setStrokePaint(new Color(Color.HSBtoRGB(h, 0.7f, 0.7f))); // if (hh>60) setStrokePaint(new Color(hh,hh,hh)); // else setStrokePaint(new Color(255-hh*2,0,0)); return rebuildStroke_old(); // return rebuildStroke_besier(); } public synchronized PPath rebuildStroke_besier() { // bezier version // float ttx2 = -1, tty2 = 0; float ttx1 = 0, tty1 = 0; Vector<double[]> v = new Vector<double[]>(); for (int i = 0; i < sx.length; i++) { float x = sx[i]; float y = sy[i]; if (x != ttx1 && y != tty1) { double[] tt = new double[2]; double[] tmid = new double[2]; if (ttx1 != 0 && tty1 != 0) { tmid[0] = (x + ttx1) / 2.0; tmid[1] = (y + tty1) / 2.0; v.add(tmid); } tt[0] = x; tt[1] = y; v.add(tt); } ttx1 = x; tty1 = y; } // FitCurves fc = new FitCurves(); // fc.getBezier(v, 4.0); // ((MyPPath)stroke).setSS(this); return this; } //自分の最後と、otherの最初の距離をみる public float distance(ShortStroke other){ if (sx.length==0) return 99999f; float tx = sx[sx.length-1]; float ty = sy[sy.length-1]; if (other.sx.length==0) return 99999f; float ox = other.sx[0]; float oy = other.sy[0]; return (float) Math.sqrt((ox-tx)*(ox-tx)+(oy-ty)*(oy-ty)); } public void move(float dx, float dy){//移動 for(int i=0;i<sx.length;i++){ sx[i] = sx[i]+dx; } for(int i=0;i<sy.length;i++){ sy[i] = sy[i]+dy; } rebuildStroke(); } public void addPoint(Point2D p) { tempPts.add(p); } /** * 生徒PDAからの生筆記データからDB用データを生成 * * @param sx X座標配列 * @param sy Y座標配列 * @return DB格納用バイトデータ */ public byte[] getXYBytes() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); BufferedOutputStream bos; DataOutputStream dos; try { bos = new BufferedOutputStream(baos); dos = new DataOutputStream(bos); dos.writeInt(sx.length); for (int i = 0; i < sx.length; i++) { dos.writeFloat(sx[i]); } for (int i = 0; i < sy.length; i++) { dos.writeFloat(sy[i]); } dos.close(); bos.close(); baos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return baos.toByteArray(); } public byte[] getPseudoPPBytes() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); BufferedOutputStream bos; DataOutputStream dos; try { bos = new BufferedOutputStream(baos); dos = new DataOutputStream(bos); dos.writeInt(sx.length); for (int i = 0; i < sx.length; i++) { dos.writeShort(128); } dos.close(); bos.close(); baos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return baos.toByteArray(); } public void debugPrint() { // System.out.println("SSDebug "+penid+" "+paperid+" "+new Date(time)); } public ShortStroke clone(){ ShortStroke newss = new ShortStroke(); newss.sx = new float[this.sx.length]; newss.sy = new float[this.sy.length]; for(int i=0;i<this.sx.length;i++){ newss.sx[i] = this.sx[i]; } for(int i=0;i<this.sy.length;i++){ newss.sy[i] = this.sy[i]; } // if (this.penpress != null){ // newss.penpress = new short[this.penpress.length]; // for(int i=0;i<this.penpress.length;i++){ // newss.penpress[i] = this.penpress[i]; // } // } newss.time = this.time; newss.penid = this.penid; newss.color = this.color; newss.width = this.width; // newss.paperid = this.paperid; newss.id = this.id; return newss; } public void play(int _interval /* PNode _ink, PNode _redink, Note n*/) { if (playing) return; // this.prepareStrokeList(_ink); // for(TimePlayPath tpp: strokelist){ // // tpp.snip.setTransparency(0.0f); // tpp.snip.setVisible(false); // } // ink = _ink; // redink = _redink; // note = n; interval = _interval; playthread = new Thread(this); playthread.start(); try { playthread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } // 現在の形状をリストに追加 public void restoreShape() { if (shapel == null) { shapel = new ArrayList<Shape>(); } Shape shape = this.getPathReference(); shapel.add(new GeneralPath(shape)); } // リセット public void resetShapes() { if (full == null) { rebuildStroke(); } if (shapel == null) { shapel = new ArrayList<Shape>(); } setPathTo(full); shapel.clear(); } // 形状を保存 public void prepareShapes() { if (shapel == null) { shapel = new ArrayList<Shape>(); } shapel.clear(); GeneralPath gp = new GeneralPath(); gp.moveTo(sx[0], sy[0]); shapel.add(new GeneralPath(gp)); for (int i = 1; i < sx.length; i++) { gp.lineTo(sx[i], sy[i]); shapel.add(new GeneralPath(gp)); } } public int getSteps() { return sx.length; } //TODO: public transient double[] speedary; public transient double[] speedary2; public transient double dist = -1; public transient double length2; public transient double avgspeed; public transient double avgspeed2; public transient double varspeed; public transient double varspeed2; public transient double maxspeed; public transient ShortStroke previous; public transient long timediff; public transient long timed; public transient double[] angleary ; public transient double[] angleary2 ; public transient double[] angleary3 ; public transient int num_choten = 0;//90度以上の点の数 public transient int num_choten2 = 0;//90度以上の点の数 ノイズ除去ver public transient double sumangle, avgangle; public transient double varangle; public transient int ramer; public transient double choten1_var; public transient double choten1_avg; public transient double choten2_var; public transient double choten2_avg; public transient int kukan2; public transient double var_oreten; public transient double var_ramer; public transient double ramerthre; public transient double ppd, pps,ppr; public transient double pts, dbltime; public int pos; //水井筆記のpos public String tag; public void print_metrics2(){ String a[] = new String[]{"var_ramer","ppd","pts","length", "current_begin"}; for(String fn: a){ Field f = null; try { f = ShortStroke.class.getField(fn); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } try { System.out.println(fn+" : "+f.get(this)); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } System.out.println(""); } public void print_metrics(){ ShortStroke clone = this.clone(); clone.calcMetrics(); String a[] = new String[]{"ramerthre","varspeed2","numrammer","var_ramer", "length"}; for(String fn: a){ Field f = null; try { f = ShortStroke.class.getField(fn); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } try { System.out.println(fn+" : "+f.get(clone)); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } System.out.println("size : "+clone.sx.length); for(double d: clone.speedary) System.out.print(d+" "); System.out.println(""); } private void log() { var_oreten = varspeed /( Math.log10(num_choten2+2)); var_ramer = varspeed / (Math.log10(ramer+2)); ppd = sx.length/dist; pps = sx.length/(ramerthre*5); ppr = sx.length/(ramer+1); pts = sx.length; dbltime = (double)(time - 1360901083972L)/1000; // System.out.println("Math.log10 = "+Math.log10(numrammer+2)); } private void ramer() { float minx=java.lang.Float.MAX_VALUE,maxx=java.lang.Float.MIN_VALUE,miny=java.lang.Float.MAX_VALUE,maxy=java.lang.Float.MIN_VALUE; for(int i=0;i<sx.length;i++){ if (sx[i] < minx) minx = sx[i]; if (sx[i] > maxx) maxx = sx[i]; if (sy[i] < miny) miny = sy[i]; if (sy[i] > maxy) maxy = sy[i]; } double w = maxx-minx; double h = maxy-miny; ramerthre = (w > h) ? w/5 : h/5; //TODO: ramer = Rammer.getRammerPoints(sx, sy, (float)ramerthre).size()-2; } private void angle() { if (sx.length > 2) { angleary = new double[sx.length-2]; num_choten = 0; //1または2か所の合計で80以上曲がっている折れ点の数を数える。 double prev_angle = -1.0; boolean isprev_choten = false; for(int i=0;i<sx.length-2;i++){ double cos = getAngle(new Point2D.Float(sx[i],sy[i]), new Point2D.Float(sx[i+1],sy[i+1]), new Point2D.Float(sx[i+2],sy[i+2])); angleary[i] = cos; if (cos > -0.17) { num_choten++; isprev_choten = true; } else if ((cos + prev_angle > -1.53) && isprev_choten==false) {//(cos > -0.8) && (prev_angle > -0.8) num_choten++; isprev_choten = true; } else { isprev_choten = false; } sumangle += cos; prev_angle = cos; } } // 初めの二つの角度について除外 if(sx.length > 4){ angleary2 = new double[sx.length-4]; double prev_angle2 = -1.0; boolean isprev_choten2 = false; num_choten2 = 0; for(int i=0;i<sx.length-4;i++){ double cos2 = getAngle(new Point2D.Float(sx[i+2],sy[i+2]), new Point2D.Float(sx[i+3],sy[i+3]), new Point2D.Float(sx[i+4],sy[i+4])); angleary2[i] = cos2; if (cos2 > -0.17) { num_choten2++; isprev_choten2 = true; } else if ((cos2 + prev_angle2 > -1.53) && isprev_choten2==false) {//(cos > -0.8) && (prev_angle > -0.8) num_choten2++; isprev_choten2 = true; } else { isprev_choten2 = false; } prev_angle2 = cos2; } //折れ点の数をノイズ分ひく if(angleary2.length > 0){ if(angleary2[angleary2.length-1] > -0.17 && speedary[speedary.length-1] < 1.0){ num_choten2--; } } if(angleary2.length > 1){ if(angleary2[angleary2.length-2] > -0.17 && (speedary[speedary.length-1]+speedary[speedary.length-2]) < 2.0){ num_choten2--; } } } } public void setPreviousSS(ShortStroke pre){ if (pre == null) return; if (pre.penid != this.penid) return; // if (pre.paperid != this.paperid) return; if (pre.id == this.id-1) { previous = pre; timediff = this.time - previous.time; long pretime = ((previous.sx.length-1)*1000)/75; timed = timediff - pretime; } } //筆記のパスの長さ(これをgetSteps()で割ったら平均速度になる) public double lengthInPixel(){ double len = 0; double len2 = 0; if (sx.length>1){ speedary = new double[sx.length-1]; for(int i=1;i<sx.length;i++){ speedary[i-1] = Math.sqrt((sx[i]-sx[i-1])*(sx[i]-sx[i-1])+(sy[i]-sy[i-1])*(sy[i]-sy[i-1])); len = len + speedary[i-1]; // System.out.println(i+"len1 :"+speedary[i-1]); } } // System.out.println(""); if (sx.length > 3) { speedary2 = new double[sx.length-3]; for(int i=3;i<sx.length;i++){ speedary2[i-3] = Math.sqrt((sx[i]-sx[i-1])*(sx[i]-sx[i-1])+(sy[i]-sy[i-1])*(sy[i]-sy[i-1])); //System.out.println("speedary : "+speedary[i-1]); len2 = len2 + speedary2[i-3]; //System.out.println(i+"len2 :"+speedary2[i-3]); } kukan2 = speedary2.length; } // System.out.println(""); if (sx.length > 4 ) { for(int i=0;i<sx.length;i++){ } // System.out.println(""); angleary3 = new double[sx.length-4]; // num_choten = 0; //1または2か所の合計で90以上曲がっている折れ点の数を数える。 但し初めの二つの角度については除外 for(int i=0;i<sx.length-4;i++){ double cos = getAngle(new Point2D.Float(sx[i+2],sy[i+2]), new Point2D.Float(sx[i+3],sy[i+3]), new Point2D.Float(sx[i+4],sy[i+4])); angleary3[i] = cos; } // System.out.println("同じ"+angleary3.length+speedary.length+sx.length); if(angleary3.length > 1){ if(angleary3[angleary3.length-1] > -0.17 && speedary[speedary.length-1] < 1.0){ // System.out.println("ts"); len2 = len2 - speedary2[speedary2.length-1]; kukan2 = kukan2 - 1; } } if(angleary3.length > 2){ if(angleary3[angleary3.length-2] > -0.17 && (speedary[speedary.length-1]+speedary[speedary.length-2]) < 2.0){ len2 = len2 - speedary2[speedary2.length-1] - speedary2[speedary2.length-2]; kukan2 = kukan2 - 2; } } } dist = len; length2 = len2; return len; } public double maxspeedInPixel(){ //最大瞬間速度 double len = 0; double tmp = 0; if (sx.length >1){ if (speedary == null) lengthInPixel(); for(int i=0;i<speedary.length;i++){ tmp = speedary[i]; if (len < tmp) len = tmp; } } maxspeed = len; return len; } public double varspeedInPixel(){//速度の分散 double var = 0; double var2 = 0; if (sx.length >1){ if (speedary == null) lengthInPixel(); avgspeed = dist/speedary.length; //平均速度 for(int i=0;i<speedary.length;i++){ double tmp = speedary[i]-avgspeed; var = var + (tmp*tmp); } var = var / speedary.length; varspeed = var; } if (sx.length >3){ if (speedary2 == null) lengthInPixel(); avgspeed2 = length2/kukan2;//平均速度 for(int i=0;i<speedary2.length;i++){ double tmp2 = speedary2[i]-avgspeed2; var2 = var2 + (tmp2*tmp2); } var2 = var2 / kukan2; varspeed2 = var2; } return var; } //なす角のcosを求める.1なら反復,-1なら直進 public static double getAngle(Point2D m1, Point2D m2, Point2D m3){ double a = m1.distance(m2); double b = m2.distance(m3); double c = m3.distance(m1); double cosC = (a*a+b*b-c*c)/(2*a*b); // System.out.println("a "+a+" b "+b+" c "+c+" cosC "+cosC); return cosC; } /** * 途中までの線を構築する */ public void showSubpath(int pos) { reset(); setPathTo(shapel.get(pos)); } public String getDateTime() { SimpleDateFormat sdf = new SimpleDateFormat("\"yyyy/MM/dd HH:mm:ss\""); return sdf.format(time); } //ストローク終了時刻とストローク開始時刻の差 public String toCsvTeinei() { return null; } public long current_begin; public double current_begin_duration; public int sec10size; public int sec30size; public int sec60size; } /* * for(int i=0;i<sx.length;i++){ float x = sx[i]; float y = sy[i]; if (x != * ttx1 && y != tty1){ if (((tty1-tty2)*(x-ttx1))!=((ttx1-ttx2)*(y-tty1))){ * double[] tt = new double[2]; tt[0] = x; tt[1] = y; v.add(tt); } ttx2 = ttx1; * tty2 = tty1; } ttx1 = x; tty1 = y; } */