Changeset 2900


Ignore:
Timestamp:
06/21/07 13:45:58 (12 years ago)
Author:
sorber
Message:

Fixed bug in selection layer generation for OverlayNodedObjects exposed by parallel adjacent segments in polylines. Added a fall-back to generate a rectangular set when less regular Gridded2DSets prove invalid. Began work on preventing consecutive colocational nodes in OverlayNodedObject.

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

Legend:

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

    r2899 r2900  
    459459  // -- OverlayNodedObject API Methods: node array mutators -- 
    460460  // note: call updateBoundingBox() after a series of changes to the node array 
     461   
    461462 
    462463  /** Sets coordinates of an existing node */ 
    463   public void setNodeCoords(int ndx, float newX, float newY) { 
    464     synchronized (nodesSync) { 
    465       nodes[0][ndx] = newX; 
    466       nodes[1][ndx] = newY; 
     464  public void setNodeCoords(int ndx, float x, float y) { 
     465    // Outline of this method: 
     466    // make sure the node isn't the same as previous or next node 
     467    // if yes, 
     468      // delete new node 
     469      // make sure previous and next aren't the same 
     470      // if they are, delete one of them 
     471    // if no, 
     472      // change the coordinates 
     473    boolean sameAsPrev = false; 
     474    boolean sameAsNext = false; 
     475    synchronized (nodesSync) { 
     476      if (ndx > 0 && (x == nodes[0][ndx-1] && y == nodes[1][ndx-1])) 
     477        sameAsPrev = true; 
     478      if (ndx < numNodes-1 && (x == nodes[0][ndx+1] && y == nodes[1][ndx+1])) 
     479        sameAsNext = true; 
     480    } 
     481     
     482    if (sameAsPrev || sameAsNext) { 
     483      if (sameAsPrev && sameAsNext) { 
     484        deleteNode(ndx+1); 
     485        deleteNode(ndx); 
     486      } 
     487      else { 
     488        deleteNode(ndx); 
     489      } 
     490    } 
     491    else { 
     492      synchronized (nodesSync) { 
     493        nodes[0][ndx] = x; 
     494        nodes[1][ndx] = y; 
     495        if (ndx == numNodes-1 && numNodes < maxNodes) { 
     496          Arrays.fill(nodes[0], numNodes, maxNodes, x); 
     497          Arrays.fill(nodes[1], numNodes, maxNodes, y); 
     498        } 
     499      } 
    467500    } 
    468501  } 
     
    471504  public void setLastNode(float x, float y) { 
    472505    setNodeCoords(numNodes-1, x, y); 
    473     synchronized (nodesSync) { 
    474       if (numNodes < maxNodes) { 
    475         Arrays.fill(nodes[0], numNodes, maxNodes, x); 
    476         Arrays.fill(nodes[1], numNodes, maxNodes, y); 
    477       } 
    478     } 
    479506  } 
    480507 
     
    487514  public void setNextNode(float x, float y) { 
    488515    synchronized (nodesSync) { 
    489       if (numNodes >= maxNodes) { 
    490         maxNodes *= 2; 
    491         resizeNodeArray(maxNodes); 
    492       } 
    493       Arrays.fill(nodes[0], numNodes, maxNodes, x); 
    494       Arrays.fill(nodes[1], numNodes++, maxNodes, y); 
    495       // i.e., set all remaining nodes (as per maxNodes) to next node coords 
     516      if (numNodes > 0 && (x == nodes[0][numNodes-1] && y == 
     517            nodes[1][numNodes-1])) { 
     518        // same as last node, do nothing 
     519      } 
     520      else { 
     521        if (numNodes >= maxNodes) { 
     522          maxNodes *= 2; 
     523          resizeNodeArray(maxNodes); 
     524        } 
     525        Arrays.fill(nodes[0], numNodes, maxNodes, x); 
     526        Arrays.fill(nodes[1], numNodes++, maxNodes, y); 
     527        // i.e., set all remaining nodes (as per maxNodes) to next node coords 
     528      } 
    496529    } 
    497530  } 
  • trunk/loci/visbio/overlays/OverlayUtil.java

    r2896 r2900  
    940940    if (len <=1) return null; 
    941941 
     942    boolean orientationChanged = false; // if this is true, right and left 
     943    // must be switched 
    942944    for (int i=0; i<len; i++) { 
    943945      float[] rightPt = new float[2]; 
    944946      float[] leftPt = new float[2]; 
    945947       
     948      // System.out.println("index = " + i); 
    946949      if (i==0) { // Case 1: the first node 
    947950        
    948         float[] p1 = new float[] {nodes[0][0], nodes[1][0]}; // first point 
    949         float[] p2 = new float[] {nodes[0][1], nodes[1][1]}; // second point 
     951        float[] p1 = new float[] {nodes[0][0], nodes[1][0]}; // first node  
     952        float[] p2 = new float[] {nodes[0][1], nodes[1][1]}; // second node 
    950953        // get a perpendicular vector to the right of p2-p1 
    951954        float[] vPerp = MathUtil.getRightPerpendicularVector2D(p2, p1); 
    952955        rightPt = MathUtil.add(p1, MathUtil.scalarMultiply(vPerp, width));  
    953956        leftPt = MathUtil.add(p1, MathUtil.scalarMultiply(vPerp, -1f * width)); 
     957        // System.out.print("First node: "); 
     958        // System.out.print("p1: "); print(p1); 
     959        // System.out.print("p2: "); print(p2); 
     960        // System.out.print("vPerp: "); print(vPerp); 
     961        // System.out.print("right pt: "); print(rightPt); 
     962        // System.out.print("left pt: "); print(leftPt); 
    954963      } 
    955964      else if (i == len - 1) { // Case 2: the last node 
    956965 
    957966        float[] p1 = new float[] {nodes[0][i-1], nodes[1][i-1]}; // penultimate 
    958         float[] p2 = new float[] {nodes[0][i], nodes[1][i]}; // last point 
     967        // node 
     968        float[] p2 = new float[] {nodes[0][i], nodes[1][i]}; // last node  
     969 
     970        boolean anti = false; 
     971        if (len >= 3) { 
     972          // test if antiparallel 
     973          float[] p0 = new float[] {nodes[0][i-2], nodes[1][i-2]}; // 3rd 2 last 
     974          float[] v1 = MathUtil.unit(MathUtil.vector(p1, p0)); 
     975          float[] v2 = MathUtil.unit(MathUtil.vector(p2, p1)); 
     976          if (MathUtil.opposite(v1, v2)) { 
     977            anti = true; 
     978            orientationChanged = orientationChanged ? false : true; // toggle 
     979          } 
     980        } 
     981 
     982        float[] vPerp; 
     983        if (anti) vPerp = 
     984          MathUtil.getRightPerpendicularVector2D(p1, p2); 
     985        // reversed p1 and p2 above! 
     986        else vPerp = MathUtil.getRightPerpendicularVector2D(p2, p1); 
     987 
    959988        // get a perpendicular vector to the right of p2-p1 
    960         float[] vPerp = MathUtil.getRightPerpendicularVector2D(p2, p1); 
    961989        // add a multiple of this vector to the point p2, the last node in 
    962990        // the curve 
    963         rightPt = MathUtil.add(p2, MathUtil.scalarMultiply(vPerp, width));  
    964         leftPt = MathUtil.add(p2, MathUtil.scalarMultiply(vPerp, -1f * width)); 
     991        float[] a = MathUtil.add(p2, MathUtil.scalarMultiply(vPerp, width));  
     992        float[] b = MathUtil.add(p2, MathUtil.scalarMultiply(vPerp, -1f * width)); 
     993        rightPt = orientationChanged ? b : a; 
     994        leftPt = orientationChanged ? a : b; 
     995 
     996        // System.out.print("\nLast node:"); 
     997        // System.out.print("p1: "); print(p1); 
     998        // System.out.print("p2: "); print(p2); 
     999        // System.out.print("vPerp: "); print(vPerp); 
     1000        // System.out.print("right pt: "); print(rightPt); 
     1001        // System.out.print("left pt: "); print(leftPt); 
     1002        // System.out.println("orientation changed = "  + orientationChanged); 
    9651003      } 
    9661004      else { // Case 3: all interior nodes 
     
    9701008        float[] p3 = {nodes[0][i+1], nodes[1][i+1]}; 
    9711009         
    972         // obtain unit vectors bisecting p2-p1 and p3-p2 
    973         float[] bisector = MathUtil.getRightBisectorVector2D(p1, p2, p3); 
    974         float[] bisectorReflected = MathUtil.scalarMultiply(bisector, -1f); 
    975  
    976         // compute angle between the p2-p1 and bisector  
    977         float sin = Math.abs(MathUtil.cross2D(bisector, 
    978               MathUtil.unit(MathUtil.vector(p2, p1)))); 
    979         if (sin < 0.1f) sin = 0.1f; // keep a lower bound on this for safety  
    980         // (the value of sin could become really small) 
    981          
    982         // compute offset distance from curve 
    983         float offset = width / sin; 
    984  
    985         rightPt = MathUtil.add(p2, MathUtil.scalarMultiply(bisector, offset)); 
    986         leftPt = MathUtil.add(p2, MathUtil.scalarMultiply(bisectorReflected, 
    987               offset)); 
     1010        // System.out.print("\nNode index " + i + ":"); 
     1011        // System.out.print("p1: "); print(p1); 
     1012        // System.out.print("p2: "); print(p2); 
     1013        // System.out.print("p3: "); print(p3); 
     1014 
     1015        // check if p2-p3 and p3-p2 are antiparallel 
     1016        // have to correct the strategy in this case 
     1017        float[] v1 = MathUtil.unit(MathUtil.vector(p2, p1)); 
     1018        float[] v2 = MathUtil.unit(MathUtil.vector(p3, p2)); 
     1019        if (MathUtil.opposite(v1, v2)) { 
     1020          // vectors are antiparallel. just use v1 to calculate right and left 
     1021          float[] vPerp = MathUtil.getRightPerpendicularVector2D(p2, p1);  
     1022          float[] a = MathUtil.add(p2, MathUtil.scalarMultiply(vPerp, width));  
     1023          float[] b = MathUtil.add(p2, MathUtil.scalarMultiply(vPerp, -1f * width)); 
     1024          rightPt = orientationChanged ? b : a; 
     1025          leftPt = orientationChanged ? a : b; 
     1026          // System.out.print("vPerp: "); print(vPerp); 
     1027          orientationChanged = orientationChanged ? false : true; // toggle 
     1028        } 
     1029        else { 
     1030          // obtain unit vectors bisecting p2-p1 and p3-p2 
     1031          float[] bisector = MathUtil.getRightBisectorVector2D(p1, p2, p3); 
     1032          float[] bisectorReflected = MathUtil.scalarMultiply(bisector, -1f); 
     1033 
     1034          // compute angle between the p2-p1 and bisector  
     1035          float sin = Math.abs(MathUtil.cross2D(bisector, 
     1036                MathUtil.unit(MathUtil.vector(p2, p1)))); 
     1037          if (sin < 0.1f) sin = 0.1f; // keep a lower bound on this for safety  
     1038          // (the value of sin could become really small) 
     1039           
     1040          // compute offset distance from curve 
     1041          float offset = width / sin; 
     1042 
     1043          float[] a = MathUtil.add(p2, MathUtil.scalarMultiply(bisector, offset)); 
     1044          float[] b = MathUtil.add(p2, MathUtil.scalarMultiply(bisectorReflected, 
     1045                offset)); 
     1046          rightPt = orientationChanged ? b : a; 
     1047          leftPt = orientationChanged ? a : b; 
     1048 
     1049          // System.out.print("bisector: "); print(bisector); 
     1050          // System.out.print("bisectorReflected: "); print(bisectorReflected); 
     1051          // System.out.print("sin = " + sin); 
     1052          // System.out.print("offset = " + offset); 
     1053        } 
     1054        // System.out.print("right pt: "); print(rightPt); 
     1055        // System.out.print("left pt: "); print(leftPt); 
     1056        // System.out.println("orientation changed = "  + orientationChanged); 
    9881057      } // end else // TEMP 
    9891058 
     
    9961065     
    9971066    // assemble an array of gridded sets representing the highlighting 
    998     Gridded2DSet[] sets = makeGridded2DSets(domain, nodes, right, left); 
     1067    Gridded2DSet[] sets = makeGridded2DSets(domain, nodes, right, left, width); 
    9991068    UnionSet fieldSets = null; 
    10001069    fieldSets = new UnionSet(domain, sets); 
     
    10111080   */    
    10121081  public static Gridded2DSet[] makeGridded2DSets(RealTupleType domain, 
    1013       float[][] nodes, float[][] right, float[][] left) { 
    1014     int len = nodes[0].length; 
     1082      float nodes[][], float[][] right, float[][] left, float width) { 
     1083 
     1084    // Note:  
     1085    // This method should probably determine whether Gridded2DSets will 
     1086    // be invalid itself, but instead it relies on VisAD's Gridded2DSet 
     1087    // constructor to do so.  If the constructor throws an exception, this 
     1088    // method tries to construct the troublesome set differently. 
     1089 
     1090    int len = left[0].length; 
    10151091    Vector sets = new Vector(100); 
    10161092    for (int i=0; i<len-1; i++) { 
     
    10401116        } 
    10411117        catch (VisADException ex2) { 
    1042           System.out.println("OverlayUtil: error making Gridded2DSets: " +  
    1043             "both tries produced invalid sets."); 
    1044           ex2.printStackTrace(); 
     1118          // make a plain rectangular set, disregarding left and right 
     1119          // arrays 
     1120          float[] p1 = {nodes[0][i], nodes[1][i]}; 
     1121          float[] p2 = {nodes[0][i+1], nodes[1][i+1]}; 
     1122 
     1123          float[] vPerp = MathUtil.getRightPerpendicularVector2D(p2, p1); 
     1124          float[] vPerpReflected = MathUtil.scalarMultiply(vPerp, -1f); 
     1125          float[] s1 = MathUtil.add(p1, vPerp);  
     1126          float[] s2 = MathUtil.add(p2, vPerp);  
     1127          float[] s3 = MathUtil.add(p1, vPerpReflected); 
     1128          float[] s4 = MathUtil.add(p2, vPerpReflected); 
     1129 
     1130          setSamples = new float[][]{ 
     1131            {s1[0], s2[0], s3[0], s4[0]}, 
     1132            {s1[1], s2[1], s3[1], s4[1]} 
     1133          }; 
     1134 
     1135          try { 
     1136            Gridded2DSet set = new Gridded2DSet(domain, setSamples, 2, 2, null,  
     1137              null, null, false); 
     1138            sets.add(set); 
     1139          } 
     1140          catch(VisADException ex3) { 
     1141            System.out.println("OverlayUtil: error making Gridded2DSets: " +  
     1142              "all three tries produced invalid sets (index " + i + ")."); 
     1143            System.out.println("left points"); 
     1144            print(left); 
     1145            System.out.println("\nright points"); 
     1146            print(right); 
     1147            ex3.printStackTrace(); 
     1148          } 
    10451149        } 
    10461150      } 
  • trunk/loci/visbio/overlays/PolylineTool.java

    r2896 r2900  
    9595    DisplayImpl display = (DisplayImpl) e.getDisplay(); 
    9696 
    97     //printMode("mouseDown"); 
     97    // printMode("mouseDown"); 
    9898 
    9999    if (overlay.hasToolChanged()) { 
     
    174174    DisplayImpl display = (DisplayImpl) e.getDisplay(); 
    175175 
    176     //printMode("mouseDrag"); 
     176    // printMode("mouseDrag"); 
    177177 
    178178    if (overlay.hasToolChanged()) { 
     
    217217    //System.out.println("up mode = " + mode); 
    218218    DisplayImpl display = (DisplayImpl) e.getDisplay(); 
    219     //printMode("mouseUp");//TEMP 
     219    // printMode("mouseUp");//TEMP 
    220220 
    221221    if (overlay.hasToolChanged()) { 
     
    259259    //System.out.println("moved mode = " + mode); 
    260260    DisplayImpl display = (DisplayImpl) e.getDisplay(); 
    261     //printMode("mouseMoved"); 
     261    // printMode("mouseMoved"); // TEMP 
    262262 
    263263    if (overlay.hasToolChanged()) { 
     
    325325    } 
    326326    else if (mode == BEG_EXTEND) { 
    327       // update curve length 
     327      // adjust last node and update curve length 
    328328      adjustLastNode(line, dx, dy); 
    329329 
     
    335335        getDistanceToNode(line.getNumNodes() - 2, px, py, display); 
    336336 
    337       // highlight first or last visible node if near 
    338       if (hdist < THRESH) { 
     337      // highlight last visible node if near head 
     338      if (line.getNumNodes() >= 3 && hdist < THRESH) { 
    339339        line.setHighlightNode(line.getNumNodes()-1, CON); 
    340340        mode = CLOSE_LOOP; 
Note: See TracChangeset for help on using the changeset viewer.