Changeset 1796


Ignore:
Timestamp:
11/15/06 14:23:31 (13 years ago)
Author:
sorber
Message:

FreeformTool now uses tendril-like editing.

Location:
trunk/loci/visbio/overlays
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/loci/visbio/overlays/FreeformTool.java

    r1724 r1796  
    3333  // -- Constants -- 
    3434 
    35   protected static final double DRAWTHRESH = 2.0; // When drawing, how far mouse must be dragged before a new node is added 
    36   protected static final double DRAGTHRESH = 2.0; // When editing, how far mouse must be dragged before a new node is added  
    37   //DRAWTHRESH and DRAGTHRESH ought to be the same 
    38   protected static final double EDITTHRESH = 5.0; // Threshhold within which click must occur to invoke edit mode 
     35  /** When drawing or editing, how far mouse must be dragged before new node is added */ 
     36  protected static final double DRAW_THRESH = 2.0;  
     37  /** Threshhold within which click must occur to invoke edit mode */ 
     38  protected static final double EDIT_THRESH = 5.0;  
     39  /** Threshhold within which click must occur to invoke extend mode or reconnect a tendril */ 
     40  protected static final double RECONNECT_THRESH = 0.5;  
    3941 
    4042  // -- Fields -- 
     
    4244  /** Curve currently being drawn or modified. */ 
    4345  protected OverlayFreeform freeform;  
    44  
    45   protected boolean editing; // whether the tool is in edit mode  
    46   protected int prevNodeIndex, nextNodeIndex; // used in editing to track changes to the curve  
    4746   
     47  /** Tendril wraps info about an edit to a curve */ 
     48  protected Tendril tendril; 
     49 
     50  protected boolean editing, extending; // whether the tool is in edit mode or extend mode; 
     51  protected int prevNodeIndex, inserted; // used in editing to track changes to the curve  
     52  protected float[][] pre, post; // chunks of curve tracked in redrawing  
     53 
    4854  // -- Constructor -- 
    4955 
     
    5157  public FreeformTool(OverlayTransform overlay) { 
    5258    super(overlay, "Freeform", "Freeform", "freeform.png"); 
    53     editing = false; 
    54     prevNodeIndex = nextNodeIndex = 0; 
    55   } 
     59    editing = extending = false; 
     60    prevNodeIndex = inserted = 0; 
     61    tendril = null; 
     62  } 
     63 
    5664  // -- OverlayTool API methods -- 
    5765 
     
    7179    OverlayFreeform target = getClosestFreeform(x, y); 
    7280     
    73     if (target == null) { 
    74       //System.out.println("target freeform for editing == null");// TEMP 
     81    if (target == null) { // not close to any freeforms 
    7582      deselectAll(); 
    7683      freeform = new OverlayFreeform(overlay, x, y, x, y); 
    7784      configureOverlay(freeform); 
    7885      overlay.addObject(freeform, pos); 
     86      extending = true; 
    7987    } else { 
    80       // ACS TODO setSelected for freeform under edit 
    81       // closestFreeform.setSelected(true); 
     88      // ACS TODO set selected in Overlays window for freeform under edit 
    8289      freeform = target; 
    83       //print("mouseDown", "Entering edit mode"); // TEMP 
    84       editing = true; 
    85  
    86       double[] distSegWt = freeform.getDistanceEtc(x, y); 
     90      editing = true; // enter edit mode 
     91 
     92      double[] distSegWt = MathUtil.getDistSegWt(freeform.getNodes(), x, y); 
    8793 
    8894      double dist = distSegWt[0]; 
     
    9298      // criteria for entering extend mode or edit mode 
    9399      if (seg + 2 == freeform.getNumNodes() && weight == 1.0) { // extend 
    94         //print("mouseDown", "case 1: nearest point is last node"); // TEMP 
    95100        editing = false; 
     101        extending = true; 
    96102      } else if (seg == 0 && weight == 0.0) { // extend 
    97         //print("mouseDown", "case 2: nearest point is first node"); // TEMP 
    98103        freeform.reverseNodes(); 
    99104        editing = false; 
     105        extending = true; 
    100106      } else { // edit 
    101         //print("mouseDown", "case 3: nearest point is interior"); // TEMP 
    102107        // project click onto curve and insert a new node there,  
    103108        // unless nearest point on curve is a node itself 
    104109        // Register this node as previous node 
    105110         
    106         // TEMP print the node array 
    107         /* 
    108         float[][] nodes = freeform.getNodes(); // TEMP 
    109         //print the nodes  
    110         for (int i=0; i<nodes[0].length; i++) // TEMP 
    111           System.out.println ("(" + nodes[0][0]+ "," + nodes[1][i]+")"); // TEMP 
    112         */ 
    113         //print ("mouseDown", ("x = " + x + " y = " + y + " seg = " + seg)); // TEMP 
    114         if (weight == 0.0) prevNodeIndex = seg; // nearest point on seg is the start node 
    115         else if (weight == 1.0) prevNodeIndex = seg + 1; // nearest point on seg is the end node 
    116         else { 
     111        if (weight == 0.0) { 
     112          // nearest point on seg is the start node 
     113          float[] a = freeform.getNodeCoords(seg); // determine projection on seg. 
     114          freeform.insertNode (seg+1, a[0], a[1]); 
     115          tendril = new Tendril (seg, seg+1, true); 
     116          splitNodes (seg-1, seg+2); 
     117        } else if (weight == 1.0) { 
     118          // nearest point on  seg is the end node 
     119          float[] a = freeform.getNodeCoords(seg+1); // determine projection on seg. 
     120          freeform.insertNode(seg+2, a[0], a[1]); 
     121          tendril = new Tendril (seg+1, seg+2, true); 
     122          splitNodes (seg, seg+3); 
     123        } else { 
    117124          float[] a = freeform.getNodeCoords(seg); // determine projection on seg. 
    118125          float[] b = freeform.getNodeCoords(seg + 1);         
    119           float dx = b[0] - a[0]; 
    120           float dy = b[1] - a[1]; 
    121           float newX = (float) (a[0] + dx * weight); 
    122           float newY = (float) (a[1] + dy * weight); 
    123           //print ("mouseDown", ("seg ("+a[0]+","+a[1]+")->("+b[0]+","+b[1]+")"));// TEMP 
    124           //print ("mouseDown", ("insert prevNode at ("+newX+","+newY+")"));// TEMP 
    125           freeform.insertNode(seg + 1, newX, newY); 
    126           prevNodeIndex = seg + 1; 
    127         } 
    128       } 
     126          float[] newXY = computePtOnSegment(a, b, (float) weight); 
     127          freeform.insertNode(seg + 1, newXY[0], newXY[1]); 
     128          freeform.insertNode(seg + 1, newXY[0], newXY[1]); 
     129          tendril = new Tendril(seg+1, seg+2, false); 
     130          splitNodes (seg+1, seg+3); 
     131        } // end else 
     132      } // end else   
     133    } // end else 
     134  } // end mouseDown 
     135 
     136  /** Wraps info for redrawing a curve.  Appears like a 'tendril' on screen */ 
     137  private class Tendril { 
     138    public int start, stop, tip; 
     139    public boolean nodal; 
     140 
     141    public Tendril (int start, int stop, boolean nodal) { 
     142      this.start = start; 
     143      this.stop = stop; 
     144      this.nodal = nodal; 
     145      // initial value of tip is nonsensical.  Use as a check.  
     146      this.tip = -1; 
     147    } 
     148 
     149    public void increment() { 
     150      tendril.tip++; 
     151      tendril.start++; 
     152      tendril.stop++; 
     153    } 
     154  } 
     155 
     156  /** Splits the node array into two parts.  The first part goes from a[0] to a[index-1], the second 
     157    * from a[index2] to a[a.length -1] */ 
     158  private void splitNodes (int index, int index2) { 
     159    // splits the array a into two (before the index specified) 
     160    float[][] a = freeform.getNodes(); 
     161    // print these guys 
     162    int depth = a.length; 
     163    int len = a[0].length; // assumes non-ragged array 
     164    pre =  new float[depth][index]; 
     165    post = new float[depth][len-index2]; 
     166    for (int i=0; i < depth; i++) { 
     167      System.arraycopy(a[i], 0, pre[i], 0, index); 
     168      System.arraycopy(a[i], index2, post[i], 0, len-index2); 
    129169    } 
    130170  } 
     
    132172  /** Instructs this tool to respond to a mouse release. */ 
    133173  public void mouseUp(float x, float y, int[] pos, int mods) { 
    134     //prevNodeIndex = -1; 
    135     //cleanup 
     174    if (editing && tendril !=null) { 
     175      // save coords of tendril root 
     176      float[] c = freeform.getNodeCoords(tendril.start); 
     177      freeform.deleteBetween(tendril.start-1, tendril.stop+1); 
     178      if (tendril.nodal) { 
     179        freeform.insertNode(tendril.start, c[0], c[1]); 
     180        printNodes(); 
     181      } 
     182    } 
     183 
     184    extending = editing = false; 
    136185    deselectAll(); 
    137186    if (freeform != null) {  
     187      inserted = 0; 
    138188      editing = false; 
    139189      freeform.truncateNodeArray(); 
     
    148198  /** Instructs this tool to respond to a mouse drag. */ 
    149199  public void mouseDrag(float x, float y, int[] pos, int mods) { 
    150     boolean shift = (mods & InputEvent.SHIFT_MASK)!=0;  
    151     // deactivates tendril-like behavior when dragging perpendicular to curve 
    152      
    153     /*  
    154     // WARNING: causes array out of bounds errors down the line 
    155     // try this to check for entering extend mode 
    156     if (freeform.getNumNodes() > 3){ 
    157       if (prevNodeIndex + 2 == freeform.getNumNodes()) { 
    158         editing = false; 
    159         freeform.deleteNode(prevNodeIndex + 1); 
    160       } else if (prevNodeIndex == 1) { 
    161         editing = false; 
    162         freeform.deleteNode(prevNodeIndex - 1); 
    163         prevNodeIndex--; 
     200    boolean shift = (mods & InputEvent.SHIFT_MASK) != 0;  
     201    // NEW!! holding shift suppresses reconnect routine, so you can redraw close to the curve.  
     202    // Why not use the wacom pen's click too? TODO 
     203    // I think the pen switch is mapped to Right Click by default, which is already grabbed by VisAD 
     204 
     205    if (editing) { 
     206       
     207      // get coords of prev node 
     208      float[] pcoordsf; 
     209      if (tendril.tip >= 0) { 
     210        // previous node is tendril.tip 
     211        pcoordsf = freeform.getNodeCoords(tendril.tip); 
     212      } else { 
     213        // previous node is tendril.start 
     214        pcoordsf = freeform.getNodeCoords(tendril.start); 
    164215      } 
    165     } 
    166     */ 
    167  
    168     if (editing) { 
    169       // get coords of prev node 
    170       float[] pcoordsf = freeform.getNodeCoords(prevNodeIndex); 
     216 
    171217      double[] pcoordsd = {(double) pcoordsf[0], (double) pcoordsf[1]}; 
    172218      double[] thiscoords = {(double) x, (double) y}; // coords of this mouseDrag event 
     219      double dragDist = MathUtil.getDistance(pcoordsd, thiscoords); 
    173220       
    174       // if mouseDrag went far enough 
    175       if (MathUtil.getDistance(pcoordsd, thiscoords) > DRAGTHRESH) {  
    176         // get distance to curve, nearest segment, weight (to determine nearest point on seg) 
    177         double[] distSegWt = freeform.getDistanceEtc(x, y); 
    178         double dist = distSegWt[0]; 
    179         int seg = (int) distSegWt[1]; 
    180         double weight = distSegWt[2]; 
    181  
    182         //print ("mouseDrag", ("nearest seg = " +seg+ " to " + (seg+1))); // TEMP 
    183          
    184         // Determine whether to switch into extend mode 
    185         if (seg + 2 == freeform.getNumNodes() && weight == 1.0) { // extend 
    186           //print("mouseDrag", "case 1: nearest point is last node"); // TEMP 
    187           // nearest node is last node 
    188           //freeform.setNodeCoords(seg+2, x, y); 
     221      // compute distance to pre, post chunks of curve 
     222      double[] distSegWtPre = MathUtil.getDistSegWt(pre, x, y); 
     223      double[] distSegWtPost = MathUtil.getDistSegWt(post, x, y); 
     224             
     225      boolean equalsCase = false; 
     226      if (distSegWtPre[0] == distSegWtPost[0]) equalsCase = true; 
     227      // Drag is equally close to both segments, wait for next drag. 
     228      // This case is extremely unlikely. 
     229 
     230      boolean closerToPost = (distSegWtPre[0] > distSegWtPost[0]); 
     231      double[] distSegWt = (closerToPost) ? distSegWtPost : distSegWtPre; 
     232      double minDist = distSegWt[0]; 
     233      int seg = (int) distSegWt[1]; 
     234      double weight = distSegWt[2]; 
     235      // ACS TODO what about equals case? wait for next drag? 
     236    
     237      // if not close to curve insert node, else reconnect 
     238      if (minDist > RECONNECT_THRESH) { 
     239        // insert a node at the drag point if drag went far enough 
     240        if (dragDist > DRAW_THRESH) {  
     241          // first drag only 
     242          if (tendril.tip < 0) { 
     243            freeform.insertNode(tendril.stop, x, y); 
     244            tendril.stop++; 
     245            tendril.tip = tendril.start + 1; 
     246          } else { // later drags 
     247            freeform.insertNode(tendril.tip+1, pcoordsf[0], pcoordsf[1]);   
     248            freeform.insertNode(tendril.tip+1, x, y); 
     249            tendril.tip++; 
     250            tendril.stop += 2; 
     251          } 
     252        } 
     253        // tendril.tip always points to a lone node (except for before first drag, where it doesn't point to a  
     254        // node at all 
     255 
     256      } else if (!shift && !equalsCase) { // reconnect with curve and delete nodes; 
     257        if (tendril.tip < 0) { 
     258          // tendril hasn't begun.  Do nothing. 
     259        } else { 
     260          //if (dragDist > DRAW_THRESH) { 
     261            // insert a node first at drag point, then reconnect 
     262            // skip this case:  There's the possibility that this drag point 
     263            // is across the curve from the previous drag point, which might  
     264            // result in a unintended zig-zag. 
     265          //} 
     266 
     267          // insert node at nearest point 
     268          int offset = (closerToPost) ? 1 + tendril.stop : 0; 
     269          // offset points to either post[0] or pre[0] 
     270          int endIndex = 0; // lame initial value. 
     271          if (weight == 0.0) { 
     272            endIndex = seg + offset; 
     273          } else if (weight == 1.0) { 
     274            endIndex = seg + 1 + offset; 
     275          } else { 
     276            float[] a = freeform.getNodeCoords(seg + offset); // determine projection on seg. 
     277            float[] b = freeform.getNodeCoords(seg + 1 + offset);         
     278            float[] newXY = computePtOnSegment (a, b, (float) weight); 
     279            int insertIndex = seg + 1 + offset;  
     280            freeform.insertNode(insertIndex, newXY[0], newXY[1]);  
     281            if (!closerToPost) { 
     282              tendril.increment(); 
     283            } 
     284            endIndex = insertIndex; 
     285          } 
     286          
     287          if (tendril.tip < endIndex) { 
     288            freeform.deleteBetween(tendril.tip, endIndex);  
     289          } else { 
     290            freeform.deleteBetween(endIndex, tendril.tip); 
     291          } 
    189292          editing = false; 
    190           //return; 
    191         } else if (seg == 0 && weight == 0.0) { // reverse and extend 
    192           //print("mouseDrag", "case 2: nearest point is first node"); // TEMP 
    193           // nearest node is first node 
    194           //freeform.setNodeCoords(0, x, y); 
    195           freeform.reverseNodes(); 
    196           editing = false; 
    197           //return; 
    198         } else { 
    199           //print("mouseDrag", "case 3: nearest point is an interior node"); // TEMP 
    200           if (weight == 0.0) { 
    201             //print ("mouseDrag", "nearest point was node " + seg ); // TEMP 
    202             nextNodeIndex = seg; // nearest point on seg is the start node 
    203           } else if (weight == 1.0) { 
    204             nextNodeIndex = seg + 1; // nearest point on seg is the end node 
    205             //print ("mouseDrag", "nearest point was node " + (seg+1)); // TEMP 
    206           } else { 
    207             //print("mouseDrag", "determining projection coords."); 
    208             float[] a = freeform.getNodeCoords(seg); // determine projection on seg. 
    209             float[] b = freeform.getNodeCoords(seg + 1);         
    210             float dx = b[0] - a[0]; 
    211             float dy = b[1] - a[1]; 
    212             float newX = (float) (a[0] + dx * weight); 
    213             float newY = (float) (a[1] + dy * weight); 
    214             //print ("mouseDrag", ("seg ("+a[0]+","+a[1]+")->("+b[0]+","+b[1]+")"));// TEMP 
    215             //print ("mouseDrag", ("insert nextNode at ("+newX+","+newY+")"));// TEMP 
    216             freeform.insertNode(seg + 1, newX, newY); 
    217             nextNodeIndex = seg + 1; 
    218             if (seg + 1 <= prevNodeIndex) prevNodeIndex++; // increment since insert occurs before 
    219           } 
    220          
    221           //debug(x, y); // TEMP 
    222           //print ("mouseDrag", ("prevNodeIndex=" + prevNodeIndex + " nextNodeIndex=" + nextNodeIndex)); // TEMP 
    223           if (prevNodeIndex == nextNodeIndex && !shift) { 
    224             // replace prevnode with two colocational nodes, insert new node at drag point 
    225             float[] prev = freeform.getNodeCoords(prevNodeIndex); 
    226             freeform.insertNode(prevNodeIndex+1, prev[0], prev[1]); 
    227             freeform.insertNode(prevNodeIndex+1, x, y); 
    228             prevNodeIndex++; 
    229             } else if (prevNodeIndex > nextNodeIndex) { 
    230             //print ("mouseDrag", "prevNode > nextNode. Deleting between nextNode and prevNode"); // TEMP 
    231             //debug(x,y); // TEMP 
    232             freeform.deleteBetween(nextNodeIndex, prevNodeIndex);  
    233             freeform.insertNode(nextNodeIndex + 1, x, y); // insert drag point just after next node/just before prevNode 
    234             prevNodeIndex = nextNodeIndex + 1; 
    235             //print ("mouseDrag", ("inserted node at nextNodeIndex + 1, prevNodeIndex = nextNodeIndex + 1 = " + prevNodeIndex)); // TEMP 
    236             //debug(x, y); // TEMP 
    237           } else if (nextNodeIndex > prevNodeIndex) { 
    238             //print ("mouseDrag", "prevNode < nextNode. Deleting between nextNode and prevNode"); // TEMP 
    239             int victims = Math.abs(nextNodeIndex - prevNodeIndex) - 1; 
    240             freeform.deleteBetween(prevNodeIndex, nextNodeIndex); 
    241             freeform.insertNode(nextNodeIndex - victims, x, y); // insert before next node (now shifted) 
    242             prevNodeIndex = nextNodeIndex - victims; 
    243           } 
    244         } // distance < DRAGTHRESH, keep waiting.  
    245       } // if block corresponding to check whether extend 
    246     } else { // end if editing.... 
    247       //print ("mouseDrag", "extend mode"); // TEMP 
     293        }            
     294      } // end reconnect logic 
     295    } else if (extending) {  
    248296      deselectAll(); 
    249297      float dx = x - freeform.getLastNodeX(); 
     
    251299      double dist = Math.sqrt (dx*dx + dy*dy); 
    252300 
    253       if (dist > DRAWTHRESH) { 
    254         //print("mouseDrag", ("distance sufficiently large. New node created at (" + x + "," + y + ")")); // TEMP 
     301      if (dist > RECONNECT_THRESH) { 
    255302        freeform.setNextNode(x, y); 
    256303      } 
    257     } // end else 
    258       overlay.notifyListeners(new TransformEvent(overlay)); 
    259   }// end mouseDrag 
    260  
     304    } else { 
     305      // case !extending !editing 
     306      // Q: can you be both not extending and not editing? 
     307      // A: yes, after succesfully redrawing a segment of the curve.  Further drags do nothing for now. 
     308    } 
     309 
     310    overlay.notifyListeners(new TransformEvent(overlay));  
     311  } // end mouseDrag 
     312   
    261313  //-- Additional methods 
    262314 
     
    274326        if (currentObject instanceof OverlayFreeform) { 
    275327          OverlayFreeform currentFreeform = (OverlayFreeform) currentObject; 
    276           // rough check: is point within CLICKTHRESH of bounding box (fast) 
    277           if (currentFreeform.getDistance(x, y) < EDITTHRESH) { 
     328          // rough check: is point within EDIT_THRESH of bounding box (fast) 
     329          if (currentFreeform.getDistance(x, y) < EDIT_THRESH) { 
    278330            // fine check: actually compute minimum distance to freeform (slower) 
    279             double[] distSegWt = currentFreeform.getDistanceEtc(x, y); 
     331            double[] distSegWt = MathUtil.getDistSegWt(currentFreeform.getNodes(), x, y); 
    280332            double distance = distSegWt[0]; 
    281             if (distance < EDITTHRESH && distance < minDistance) { 
     333            if (distance < EDIT_THRESH && distance < minDistance) { 
    282334              minDistance = distance; 
    283335              closestFreeform = currentFreeform; 
    284336            } 
    285           } // end (.. < EDITTHRESH) 
     337          } // end (.. < EDIT_THRESH) 
    286338        } // end if 
    287339      } // end for  
     
    290342  } 
    291343 
    292   /** Print some helpful debugging info */ 
    293   private void debug(float x, float y) { 
    294     System.out.println ("Current drag coords: (" + x + "," + y + ")"); 
    295     System.out.println ("PrevNodeIndex = " + prevNodeIndex); 
    296     System.out.println ("NextNodeIndex = " + nextNodeIndex); 
    297   } 
    298   
     344  /** Computes a point along the line segment a[]-b[] (2D) based on parameter weight */ 
     345  private float[] computePtOnSegment (float[] a, float[] b, float weight) { 
     346    float dx = b[0] - a[0]; 
     347    float dy = b[1] - a[1]; 
     348    float newX = (float) (a[0] + dx * weight); 
     349    float newY = (float) (a[1] + dy * weight); 
     350    float[] retvals = {newX, newY}; 
     351    return retvals; 
     352  } 
     353 
     354  /** Prints node array of current freeform; for debugging */ 
     355  private void printNodes() { 
     356    if (freeform!=null){  
     357      System.out.println("Printing nodes..."); 
     358      float[][]nodes = freeform.getNodes(); 
     359      for (int i = 0; i < nodes[0].length; i++){ 
     360        System.out.println(i+":("+nodes[0][i]+","+nodes[1][i]+")"); 
     361      } 
     362    } 
     363  } 
     364 
    299365  /** Prints a message for debugging */ 
    300366  public void print(String methodName, String message) {  
  • trunk/loci/visbio/overlays/OverlayIO.java

    r1390 r1796  
    7171      if (!foundHeader) { 
    7272        // parse table header from first valid line 
    73         int numDims = count - 10; 
     73       int numDims = count - 10; // why 10? 
    7474        if (numDims < 0) { 
    7575          JOptionPane.showMessageDialog(owner, 
  • trunk/loci/visbio/overlays/OverlayObject.java

    r1717 r1796  
    1 // 
     1 
    22// OverlayObject.java 
    33// 
     
    2828import java.util.Arrays; 
    2929import visad.*; 
    30 import loci.visbio.util.MathUtil; 
    3130 
    3231/** OverlayObject is the superclass of all overlay objects. */ 
     
    402401    Arrays.fill(nodes[1], numNodes++, maxNodes, y); 
    403402    // i.e., set all remaining nodes (as per maxNodes) to next node coords 
    404   } 
    405  
    406  // This could belong to MathUtil.java ACS TODO 
    407  /**  Gets actual distance to curve: finds out if the nearest point is a node or a segment;  
    408    *  
    409    *  @param x x coordinate of point in question 
    410    *  @param y y coordinate of point in question 
    411    *  @return an array float[3], with element 0 being node index i of one end of  
    412    *  closest line segment (the other end being i+1), and the third being the weight  
    413    *  between zero and one for interpolation along the segment (i, i+1) 
    414    */  
    415   public double[] getDistanceEtc(float x, float y) { 
    416     double minDist = Double.MAX_VALUE; 
    417     int seg = 0; 
    418     double weight = 0;    
    419  
    420     // toss out the trivial case 
    421     if (numNodes == 1) { 
    422       //then distance is the distance to the trivial bounding box after all; could invoke the  
    423       //getDistance method from OverlayFreeform instead. 
    424       double xdist = x - nodes[0][0]; 
    425       double ydist = y - nodes[1][0]; 
    426       minDist = Math.sqrt(xdist * xdist + ydist * ydist); 
    427     } else { 
    428  
    429       for (int i=0; i<numNodes-1; i++) { 
    430          double[] a = {(double) nodes[0][i], (double) nodes[1][i]}; 
    431          double[] b = {(double) nodes[0][i+1], (double) nodes[1][i+1]}; 
    432          double[] p = {(double) x, (double) y}; 
    433  
    434          double[] proj = MathUtil.getProjection(a, b, p, true); 
    435          double dist = MathUtil.getDistance(p, proj); 
    436  
    437          if (dist < minDist) { 
    438            minDist = dist; 
    439            seg = i; 
    440            double segDist = MathUtil.getDistance (a, b); 
    441            double fracDist = MathUtil.getDistance (a, proj); 
    442            weight = fracDist / segDist; 
    443          } 
    444        }  
    445     } 
    446     double[] retvals = {minDist, (double) seg, weight}; 
    447     return retvals; 
    448403  } 
    449404 
Note: See TracChangeset for help on using the changeset viewer.