Changeset 2653


Ignore:
Timestamp:
04/20/07 17:39:58 (13 years ago)
Author:
sorber
Message:

Invisible overlay objects aren't rendered.
Invisible overlay objects delete themselves.
Returned to hard-coded selection layer width.
Added StatsOptionsPane class.
Added menu allowing users to choose which statistics to save/export.

Location:
trunk/loci/visbio/overlays
Files:
1 added
19 edited

Legend:

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

    r2246 r2653  
    6262    if (arrow == null) return; 
    6363    arrow.setDrawing(false); 
     64    if (!arrow.hasData()) overlay.removeObject(arrow); 
    6465    arrow = null; 
    6566    overlay.notifyListeners(new TransformEvent(overlay)); 
  • trunk/loci/visbio/overlays/BoxTool.java

    r2246 r2653  
    6262    if (box == null) return; 
    6363    box.setDrawing(false); 
    64  
    65     if (box.getX() == box.getX2() || box.getY() == box.getY2()) { 
    66       overlay.removeObject(box); 
    67     } 
    68  
     64    if (!box.hasData()) overlay.removeObject(box);  
    6965    box = null; 
    7066    overlay.notifyListeners(new TransformEvent(overlay)); 
  • trunk/loci/visbio/overlays/FreeformTool.java

    r2623 r2653  
    3232import visad.util.CursorUtil; 
    3333 
     34 
     35//goals:  
     36// eliminate errors in code 
     37// make code readable  
     38// consolidate code where possible 
     39 
    3440/** FreeformTool is the tool for creating freeform objects. */ 
    3541public class FreeformTool extends OverlayTool { 
     
    109115    float dx, float dy, int[] pos, int mods) 
    110116  { 
    111     // -- housekeeping 
    112117    boolean ctl = (mods & InputEvent.CTRL_MASK) != 0; 
    113118    DisplayImpl display = (DisplayImpl) e.getDisplay(); 
     
    149154        if (ctl && dist < ERASE_THRESH) { 
    150155          // split and enter erase mode 
    151           slice(freeform, dx, dy, dist, seg, weight); 
     156          slice(freeform, dist, seg, weight); 
    152157          freeform = null; 
    153158        } 
     
    164169            freeform.insertNode(seg+2, a[0], a[1]); 
    165170            tendril = new Tendril (seg+1, seg+2, true); 
    166             splitNodes (seg, seg+3); 
     171            splitNodes (freeform, seg, seg+3); 
    167172          } 
    168173          else { 
     
    174179            freeform.insertNode(seg + 1, newXY[0], newXY[1]); 
    175180            tendril = new Tendril(seg+1, seg+2, false); 
    176             splitNodes (seg+1, seg+3); 
     181            splitNodes (freeform, seg+1, seg+3); 
    177182          } 
    178183          setMode(EDIT); 
     
    332337            lastDbl[0] = (double) last[0]; 
    333338            lastDbl[1] = (double) last[1]; 
    334  
    335             // DISTANCE COMPUTATION  
    336             // floats and doubles 
    337339            delta = MathUtil.getDistance (nearest, lastDbl); 
    338340            freeform.setCurveLength(freeform.getCurveLength() - delta); 
    339341 
    340             // delete last node node 
     342            // delete last node 
    341343            freeform.deleteNode(index); 
    342             // WARNING: this is O(n) expensive. 
    343             // Maybe remove it and just update at mouseUp? 
    344             freeform.updateBoundingBox(); 
     344            if (!freeform.hasData()) { 
     345             setMode(CHILL); 
     346            } 
    345347          } 
    346348          else setMode(DRAW); 
    347           if (freeform.getNumNodes() == 0) setMode(CHILL); 
    348349        } 
    349350      } 
     
    486487   
    487488  /** Slices a freeform in two. */ 
    488   private void slice(OverlayFreeform freef, 
    489     float dx, float dy, double dist, int seg, double weight) 
     489  private void slice(OverlayFreeform freef, double dist, int seg, double weight) 
    490490  { 
    491491    int f1Start, f2Start, f1Stop, f2Stop; 
     
    576576   * a[index-1], the second from a[index2] to a[a.length -1]. 
    577577   */ 
    578   private void splitNodes(int index, int index2) { 
     578  private void splitNodes(OverlayFreeform freeform, int index, int index2) { 
    579579    // splits the array a into two (before the index specified) 
    580580    float[][] a = freeform.getNodes(); 
     
    597597    mode = newMode; 
    598598 
    599      
    600599    if (mode == INIT) { 
    601600    } 
     
    628627      otherFreefs.removeAllElements(); 
    629628      if (freeform != null) { 
    630         if (freeform.getNumNodes() <= 1) overlay.removeObject(freeform); 
     629        freeform.setDrawing(false); 
     630        if (!freeform.hasData()) { 
     631          overlay.removeObject(freeform); 
     632        } 
    631633        else { 
    632634          freeform.computeLength(); 
    633635          freeform.updateBoundingBox(); 
    634636          freeform.computeGridParameters(); 
    635           freeform.setDrawing(false); 
    636637          freeform.setSelected(true); 
    637638          freeform = null; 
  • trunk/loci/visbio/overlays/LineTool.java

    r2246 r2653  
    6060    if (line == null) return; 
    6161    line.setDrawing(false); 
    62     if (line.getX() == line.getX2() && line.getY() == line.getY2()) { 
    63       overlay.removeObject(line); 
    64     } 
     62    if (!line.hasData()) overlay.removeObject(line); 
    6563    line = null; 
    6664    overlay.notifyListeners(new TransformEvent(overlay)); 
  • trunk/loci/visbio/overlays/OvalTool.java

    r2246 r2653  
    6262    if (oval == null) return; 
    6363    oval.setDrawing(false); 
    64  
    65     if (oval.getX() == oval.getX2() || oval.getY() == oval.getY2()) { 
    66       overlay.removeObject(oval); 
    67     } 
    68  
     64    if (!oval.hasData()) overlay.removeObject(oval); 
    6965    oval = null; 
    7066    overlay.notifyListeners(new TransformEvent(overlay)); 
  • trunk/loci/visbio/overlays/OverlayArrow.java

    r2615 r2653  
    3232/** OverlayArrow is an arrow wedge overlay. */ 
    3333public class OverlayArrow extends OverlayObject { 
     34 
     35  // -- Static Fields -- 
     36 
     37  /** The names of the statistics this object reports */ 
     38  protected static String[] statTypes = {"Tip coordinates", "Angle", 
     39    "Length"}; 
    3440 
    3541  // -- Constructors -- 
     
    5056  } 
    5157 
     58  // -- Static methods -- 
     59 
     60  /** Returns the names of the statistics this object reports */ 
     61  public static String[] getStatTypes() {return statTypes;} 
     62 
    5263  // -- OverlayObject API methods -- 
    5364 
    5465  /** Gets VisAD data object representing this overlay. */ 
    5566  public DataImpl getData() { 
    56     if (x1 == x2 && y1 == y2) return null; // dont render zero length arrows 
     67    if (!hasData()) return null; // dont render zero length arrows 
    5768    float padding = 0.02f * overlay.getScalingValue(); 
    5869    double xx = x2 - x1; 
     
    105116  } 
    106117 
     118  /** Returns whether this object is drawable, i.e., is of nonzero  
     119   *  size, area, length, etc.  
     120   */ 
     121  public boolean hasData() { return (x1 != x2 || y1 != y2); } 
     122 
    107123  /** Computes the shortest distance from this object to the given point. */ 
    108124  public double getDistance(double x, double y) { 
     
    116132  /** Gets a selection grid for this object */ 
    117133  public DataImpl getSelectionGrid(boolean outline) { 
    118     if (x1 == x2 && y1 == y2) return null; // dont render zero length arrows 
     134    if (!hasData()) return null; // dont render zero length arrows 
    119135    else if (outline) return super.getSelectionGrid(true); 
    120136 
     
    191207  } 
    192208 
     209  /** Returns a specific statistic of this object */ 
     210  public String getStat(String name) { 
     211    if (name.equals("Tip coordinates")) { 
     212      return "(" + x1 + ", " + y1 + ")"; 
     213    }  
     214    else if (name.equals("Angle")) { 
     215      return "" + getAngle(); 
     216    }  
     217    else if (name.equals("Length")) { 
     218      return "" + getLength(); 
     219    } 
     220    else return "No such statistic for this overlay type"; 
     221  } 
     222 
    193223  /** Retrieves useful statistics about this overlay. */ 
    194224  public String getStatistics() { 
    195     float xx = x2 - x1; 
    196     float yy = y2 - y1; 
    197     float angle = (float) (180 * Math.atan(xx / yy) / Math.PI); 
    198     if (yy < 0) angle += 180; 
    199     if (angle < 0) angle += 360; 
    200     float length = (float) Math.sqrt(xx * xx + yy * yy); 
    201  
    202225    return "Arrow tip coordinates = (" + x1 + ", " + y1 + ")\n" + 
    203       "Angle = " + angle + "; Length = " + length; 
     226      "Angle = " + getAngle() + "; Length = " + getLength(); 
    204227  } 
    205228 
     
    247270  } 
    248271 
     272  // -- Helper methods -- 
     273   
     274  /** Computes the angle of this arrow */ 
     275  protected float getAngle() { 
     276    float xx = x2 - x1; 
     277    float yy = y2 - y1; 
     278    float angle = (float) (180 * Math.atan(xx / yy) / Math.PI); 
     279    if (yy < 0) angle += 180; 
     280    if (angle < 0) angle += 360; 
     281    return angle; 
     282  } 
     283 
     284  /** Computes the length of this arrow */ 
     285  protected float getLength() {  
     286    float xx = x2 - x1; 
     287    float yy = y2 - y1; 
     288    float length = (float) Math.sqrt(xx * xx + yy * yy); 
     289    return length; 
     290  } 
     291 
    249292  // -- Object API methods -- 
    250293 
  • trunk/loci/visbio/overlays/OverlayBox.java

    r2591 r2653  
    3131/** OverlayBox is a rectangle overlay. */ 
    3232public class OverlayBox extends OverlayObject { 
     33 
     34  // -- Static Fields -- 
     35   
     36  /** The names of the statistics this object reports */ 
     37  protected static String[] statTypes =  {"Coordinates", "Center", "Width",  
     38    "Height", "Area", "Perimeter"}; 
    3339 
    3440  // -- Constructors -- 
     
    4955  } 
    5056 
    51   // -- Static OverlayObject API methods --  
    52   /** Returns the types of statistics reported by this overlay */ 
    53   public static String[] getStatTypes() {   
    54     return new String[] {"Coordinates", "Center", "Width", "Height", "Area", 
    55         "Perimeter"}; 
    56   } 
     57  // -- Static methods -- 
     58 
     59  /** Returns the names of the statistics this object reports */ 
     60  public static String[] getStatTypes() {return statTypes;} 
    5761 
    5862  // -- OverlayObject API methods -- 
     
    6064  /** Gets VisAD data object representing this overlay. */ 
    6165  public DataImpl getData() { 
    62     if (x1 == x2 || y1 == y2) return null;  
     66    if (!hasData()) return null;  
    6367    // don't try to render a zero-area box 
    6468    RealTupleType domain = overlay.getDomainType(); 
     
    110114  } 
    111115 
     116  /** Returns whether this object is drawable, i.e., is of nonzero  
     117   *  size, area, length, etc.  
     118   */ 
     119  public boolean hasData() { return (x1 != x2 && y1 != y2); } 
     120 
    112121  /** Computes the shortest distance from this object to the given point. */ 
    113122  public double getDistance(double x, double y) { 
     
    121130  } 
    122131 
     132  /** Returns a specific statistic of this object*/ 
     133  public String getStat(String name) { 
     134    float xx = x2 - x1; 
     135    float yy = y2 - y1; 
     136    float width = xx < 0 ? -xx : xx; 
     137    float height = yy < 0 ? -yy : yy; 
     138    float centerX = x1 + xx / 2; 
     139    float centerY = y1 + yy / 2; 
     140    float area = width * height; 
     141    float perim = width + width + height + height; 
     142 
     143    if (name.equals("Coordinates")) { 
     144      return "(" + x1 + ", " + y1 + ")-(" + x2 + ", " + y2 + ")"; 
     145    }  
     146    else if (name.equals("Center")) { 
     147      return "(" + centerX + ", " + centerY + ")";  
     148    }  
     149    else if (name.equals("Width")) { 
     150      return "" + width; 
     151    } 
     152    else if (name.equals("Height")) { 
     153      return "" + height; 
     154    } 
     155    else if (name.equals("Area")) { 
     156      return "" + area; 
     157    } 
     158    else if (name.equals("Perimeter")) { 
     159      return "" + perim; 
     160    } 
     161    else return "No such statistic for this overlay type"; 
     162  } 
     163   
    123164  /** Retrieves useful statistics about this overlay. */ 
    124165  public String getStatistics() { 
     
    139180  } 
    140181 
    141   /** Gets this object's statistics in array */ 
    142   public OverlayStat[] getStatisticsArray() { 
    143     float xx = x2 - x1; 
    144     float yy = y2 - y1; 
    145     float width = xx < 0 ? -xx : xx; 
    146     float height = yy < 0 ? -yy : yy; 
    147     float centerX = x1 + xx / 2; 
    148     float centerY = y1 + yy / 2; 
    149     float area = width * height; 
    150     float perim = width + width + height + height; 
    151  
    152     String coords = "(" + x1 + ", " + y1 + ")-(" + x2 + ", " + y2 + ")"; 
    153     String center = "(" + centerX + ", " + centerY + ")"; 
    154      
    155     OverlayStat[] stats = { 
    156       new OverlayStat("Coordinates", coords), 
    157       new OverlayStat("Center", "" + center), 
    158       new OverlayStat("Width", "" + width), 
    159       new OverlayStat("Height", "" + height), 
    160       new OverlayStat("Area", "" + area), 
    161       new OverlayStat("Perimeter", "" + perim) 
    162     }; 
    163  
    164     return stats; 
    165   } 
    166  
    167182  /** True iff this overlay has an endpoint coordinate pair. */ 
    168183  public boolean hasEndpoint() { return true; } 
     
    201216 
    202217  public DataImpl getSelectionGrid(boolean outline) { 
     218    if (!hasData()) return null; 
     219    else if (outline) return super.getSelectionGrid(outline); 
     220 
    203221    RealTupleType domain = overlay.getDomainType(); 
    204222    TupleType range = overlay.getRangeType(); 
  • trunk/loci/visbio/overlays/OverlayIO.java

    r2593 r2653  
    3232import javax.swing.JOptionPane; 
    3333import loci.formats.FormatTools; 
     34import loci.visbio.state.BooleanOption; 
     35import loci.visbio.state.OptionManager; 
     36import loci.visbio.util.*; 
    3437import loci.visbio.VisBio; 
    35 import loci.visbio.util.*; 
     38import loci.visbio.VisBioFrame; 
    3639import org.apache.poi.hssf.usermodel.*; 
    3740import org.apache.poi.hssf.util.Region; 
     
    436439    Vector[] vectors = {lines, freeforms, markers, texts, ovals, boxes,  
    437440      arrows, polylines}; 
    438     String[] titles = {"Line", "Freeform", "Marker", "Text", "Oval", "Box", 
    439       "Arrow", "Polyline"}; 
     441    String[] titles = OverlayStat.getOverlayTypes(); 
    440442    for (int v=0; v<vectors.length; v++) { 
    441       if (vectors[v].size() > 0)  
    442       { 
    443         out.println(); // Throw in a blank 
    444         out.println("# " + titles[v] + " Statistics"); 
    445         for (int i=0; i<vectors[v].size(); i++)  
    446         { 
    447           OverlayObject obj = (OverlayObject) vectors[v].get(i); 
    448           int index = i + 1; 
    449           out.println("# " + titles[v] + " " + index); 
    450           OverlayStat[] stats = obj.getStatisticsArray(); 
    451           for (int j=0; j<stats.length; j++)  
    452           { 
    453                   out.println("#\t" + stats[j].getName() + "\t" + stats[j].getValue()); 
    454           } 
    455         } 
     443      if (vectors[v].size() > 0) { 
     444        out.println(); // Throw in a blank 
     445        out.println("# " + titles[v] + " Statistics"); 
     446        for (int i=0; i<vectors[v].size(); i++) { 
     447          OverlayObject obj = (OverlayObject) vectors[v].get(i); 
     448          int index = i + 1; 
     449          out.println("# " + titles[v] + " " + index); 
     450          String[] stats = OverlayStat.getStatTypes(titles[v]); 
     451          OptionManager om = (OptionManager) 
     452            VisBioFrame.getVisBio().getManager(OptionManager.class); 
     453          for (int j=0; j<stats.length; j++) { 
     454            String name = titles[v] + "." + stats[j]; 
     455            BooleanOption option = (BooleanOption) om.getOption(name); 
     456            // print if option is selected 
     457            if (option.getValue()) { 
     458              out.println("#\t" + stats[j] + "\t" + 
     459                obj.getStat(stats[j])); 
     460            } 
     461          } 
     462        } 
    456463      } 
    457464    } 
     
    585592 
    586593        // a 'rider' to this loop: keep track of noded objects 
    587         if (obj instanceof OverlayLine) lines.add(obj); 
    588         if (obj instanceof OverlayFreeform) freeforms.add(obj); 
    589         if (obj instanceof OverlayMarker) markers.add(obj); 
    590         if (obj instanceof OverlayText) texts.add(obj); 
    591         if (obj instanceof OverlayOval) ovals.add(obj); 
    592         if (obj instanceof OverlayBox) boxes.add(obj); 
    593         if (obj instanceof OverlayArrow) arrows.add(obj); 
    594         if (obj instanceof OverlayPolyline) polylines.add(obj); 
     594        if (obj instanceof OverlayLine) lines.add(obj); 
     595        if (obj instanceof OverlayFreeform) freeforms.add(obj); 
     596        if (obj instanceof OverlayMarker) markers.add(obj); 
     597        if (obj instanceof OverlayText) texts.add(obj); 
     598        if (obj instanceof OverlayOval) ovals.add(obj); 
     599        if (obj instanceof OverlayBox) boxes.add(obj); 
     600        if (obj instanceof OverlayArrow) arrows.add(obj); 
     601        if (obj instanceof OverlayPolyline) polylines.add(obj); 
    595602 
    596603        // overlay object type 
     
    630637        // x2 
    631638        c = r.createCell(cellnum++); 
    632         if (obj.hasEndpoint()) {  
     639        if (obj.hasEndpoint2()) {  
    633640          c.setCellStyle(flt); 
    634641          c.setCellValue(obj.x2); 
     
    641648        // y2  
    642649        c = r.createCell(cellnum++); 
    643         if (obj.hasEndpoint()) {  
     650        if (obj.hasEndpoint2()) {  
    644651          c.setCellStyle(flt); 
    645652          c.setCellValue(obj.y2); 
     
    683690    Vector[] vectors = {lines, freeforms, markers, texts, ovals, boxes,  
    684691      arrows, polylines}; 
    685     String[] titles =  
    686       { "Line", "Freeform", "Marker", "Text", "Oval", "Box", 
    687         "Arrow", "Polyline"}; 
    688     for (int v=0; v<vectors.length; v++)  
    689     { 
    690       if (vectors[v].size() > 0)  
    691       { 
    692         rownum += 2; 
    693         r = s.createRow(rownum); 
    694         cellnum = 0; 
    695         c = r.createCell(cellnum++); 
    696         c.setCellStyle(text); 
    697         c.setCellValue(new HSSFRichTextString(titles[v] + " Statistics")); 
    698                                
    699         for (int i=0; i<vectors[v].size(); i++)  
    700         { 
    701           OverlayObject obj = (OverlayObject) vectors[v].get(i); 
    702           int index = i + 1; 
    703            
    704           cellnum = 0; 
    705           r = s.createRow(++rownum); 
    706           c = r.createCell(cellnum++); 
    707           c.setCellStyle(text); 
    708           c.setCellValue(new HSSFRichTextString(titles[v] + " " + index)); 
    709            
    710           OverlayStat[] stats = obj.getStatisticsArray(); 
    711           for (int j=0; j<stats.length; j++)  
    712           { 
    713             r = s.createRow(++rownum); 
    714             cellnum = 1; // indent one column 
    715             c = r.createCell(cellnum++); 
    716             c.setCellStyle(text); 
    717             c.setCellValue(new HSSFRichTextString(stats[j].getName())); 
    718              
    719             c = r.createCell(cellnum++); 
    720             c.setCellStyle(text); 
    721             c.setCellValue(new HSSFRichTextString(stats[j].getValue())); 
    722           }  
    723         } 
    724       }  
     692    String[] titles = OverlayStat.getOverlayTypes();  
     693    for (int v=0; v<vectors.length ; v++) { 
     694      if (vectors[v].size() > 0) { 
     695        rownum += 2; 
     696        r = s.createRow(rownum); 
     697        cellnum = 0; 
     698        c = r.createCell(cellnum++); 
     699        c.setCellStyle(text); 
     700        c.setCellValue(new HSSFRichTextString(titles[v] + " Statistics")); 
     701                   
     702        for (int i=0; i<vectors[v].size(); i++) { 
     703          OverlayObject obj = (OverlayObject) vectors[v].get(i); 
     704          int index = i + 1; // index from 1 for readability 
     705           
     706          cellnum = 0; 
     707          r = s.createRow(++rownum); 
     708          c = r.createCell(cellnum++); 
     709          c.setCellStyle(text); 
     710          c.setCellValue(new HSSFRichTextString(titles[v] + " " + index)); 
     711           
     712          String[] statTypes = OverlayStat.getStatTypes(titles[v]); 
     713          OptionManager om = (OptionManager) 
     714            VisBioFrame.getVisBio().getManager(OptionManager.class); 
     715 
     716          for (int j=0; j<statTypes.length; j++) { 
     717            String name = titles[v] + "." + statTypes[j]; 
     718            BooleanOption option = (BooleanOption) om.getOption(name); 
     719            // print if option is selected 
     720            if (option.getValue()) { 
     721              r = s.createRow(++rownum); 
     722              cellnum = 1; // indent one column 
     723              c = r.createCell(cellnum++); 
     724              c.setCellStyle(text); 
     725              c.setCellValue(new HSSFRichTextString(statTypes[j])); 
     726               
     727              c = r.createCell(cellnum++); 
     728              c.setCellStyle(text); 
     729              c.setCellValue(new HSSFRichTextString(obj.getStat(statTypes[j]))); 
     730            } 
     731          }  
     732        } 
     733      } 
    725734    }  
    726735 
  • trunk/loci/visbio/overlays/OverlayLine.java

    r2561 r2653  
    3232/** OverlayLine is a measurement line overlay. */ 
    3333public class OverlayLine extends OverlayObject { 
     34 
     35  // -- Static Fields --  
     36   
     37  /** The names of the statistics this object reports */ 
     38  protected static String[] statTypes =  {"Coordinates", "Length"}; 
    3439 
    3540  // -- Constructors -- 
     
    5055  } 
    5156 
     57  // -- Static methods -- 
     58 
     59  /** Returns the names of the statistics this object reports */ 
     60  public static String[] getStatTypes() {return statTypes;} 
     61 
    5262  // -- OverlayObject API methods -- 
     63 
     64  /** Returns whether this object is drawable, i.e., is of nonzero  
     65  *  size, area, length, etc.  
     66  */ 
     67  public boolean hasData() { return (x1 != x2 || y1 != y2); } 
    5368 
    5469  /** Gets VisAD data object representing this overlay. */ 
    5570  public DataImpl getData() { 
     71    if (!hasData()) return null; 
     72 
    5673    RealTupleType domain = overlay.getDomainType(); 
    5774    TupleType range = overlay.getRangeType(); 
     
    89106  } 
    90107 
     108  /** Returns a specific statistic of this object */ 
     109  public String getStat(String name) { 
     110    if (name.equals("Coordinates")) { 
     111      return "(" + x1 + ", " + y1 + ")-(" + x2 + ", " + y2 + ")"; 
     112    }  
     113    else if (name.equals("Length")) { 
     114      float xx = x2 - x1; 
     115      float yy = y2 - y1; 
     116      float length = (float) Math.sqrt(xx * xx + yy * yy); 
     117      return "" + length; 
     118    }  
     119    else return "No such statistic for this overlay type"; 
     120  } 
     121  
    91122  /** Retrieves useful statistics about this overlay. */ 
    92123  public String getStatistics() { 
     
    98129      ")-(" + x2 + ", " + y2 + ")\n" + 
    99130      "Length = " + length; 
    100   } 
    101  
    102   /** Gets this object's statistics in array */ 
    103   public OverlayStat[] getStatisticsArray() { 
    104     float xx = x2 - x1; 
    105     float yy = y2 - y1; 
    106     float length = (float) Math.sqrt(xx * xx + yy * yy); 
    107      
    108     String coords = "(" + x1 + ", " + y1 + ")-(" + x2 + ", " + y2 + ")"; 
    109     OverlayStat[] stats = { 
    110       new OverlayStat("Coordinates", coords), 
    111       new OverlayStat("Length", "" + length), 
    112     }; 
    113  
    114     return stats; 
    115131  } 
    116132 
     
    170186 
    171187  public DataImpl getSelectionGrid(boolean outline) { 
     188    if (!hasData()) return null; 
     189    else if (outline) return super.getSelectionGrid(outline); 
     190 
    172191    RealTupleType domain = overlay.getDomainType(); 
    173192    TupleType range = overlay.getRangeType(); 
  • trunk/loci/visbio/overlays/OverlayManager.java

    r1390 r2653  
    2727import loci.visbio.data.DataManager; 
    2828import loci.visbio.help.HelpManager; 
     29import loci.visbio.state.OptionManager; 
    2930 
    3031/** OverlayManager is the manager encapsulating VisBio's overlay logic. */ 
     
    5960    dm.registerDataType(OverlayTransform.class, "Overlays"); 
    6061 
     62    // register Overlay options 
     63    OptionManager om = (OptionManager) bio.getManager(OptionManager.class); 
     64    String[] overlayTypes = OverlayStat.getOverlayTypes(); 
     65    for (int i=0; i<overlayTypes.length; i++) { 
     66      String[] statTypes = OverlayStat.getStatTypes(overlayTypes[i]); 
     67      for (int j=0; j<statTypes.length; j++) { 
     68        String name = overlayTypes[i] + "." + statTypes[j]; 
     69        om.addBooleanOption("Overlays", name, '|', 
     70            "Toggles whether the " + name + " statistic is exported or saved", 
     71            true); 
     72      } 
     73    } 
     74 
    6175    // help window 
    6276    bio.setSplashStatus(null); 
  • trunk/loci/visbio/overlays/OverlayMarker.java

    r2534 r2653  
    3131/** OverlayMarker is a marker crosshairs overlay. */ 
    3232public class OverlayMarker extends OverlayObject { 
     33   
     34  // -- Static Fields --  
     35   
     36  /** The names of the statistics this object reports */ 
     37  protected static String[] statTypes =  {"Coordinates"}; 
    3338 
    3439  // -- Constructors -- 
     
    4550  } 
    4651 
     52  // -- Static methods -- 
     53 
     54  /** Returns the names of the statistics this object reports */ 
     55  public static String[] getStatTypes() {return statTypes;} 
     56 
    4757  // -- OverlayObject API methods -- 
    4858 
    4959  /** Gets VisAD data object representing this overlay. */ 
    5060  public DataImpl getData() { 
     61    if (!hasData()) return null; 
    5162    RealTupleType domain = overlay.getDomainType(); 
    5263    TupleType range = overlay.getRangeType(); 
     
    8091  } 
    8192 
     93  /** Returns whether this object is drawable, i.e., is of nonzero  
     94   *  size, area, length, etc.  
     95   */ 
     96  public boolean hasData() { return true; } 
     97 
    8298  /** Gets a DataImpl overlay indicating that this object is selected */ 
    8399  public DataImpl getSelectionGrid() { return getSelectionGrid(false); } 
     
    85101  /** Gets a DataImpl overlay indicating that this object is selected */ 
    86102  public DataImpl getSelectionGrid(boolean outline) { 
    87     if (outline) return super.getSelectionGrid(outline); 
     103    if (!hasData()) return null; 
     104    else if (outline) return super.getSelectionGrid(outline); 
    88105 
    89106    RealTupleType domain = overlay.getDomainType(); 
     
    205222  } 
    206223     
    207  
    208224  /** Computes the shortest distance from this object to the given point. */ 
    209225  public double getDistance(double x, double y) { 
     
    213229  } 
    214230 
     231  /** Returns a specific statistic of this object*/ 
     232  public String getStat(String name) { 
     233    if (name.equals("Coordinates")) { 
     234      return "(" + x1 + ", " + y1 + ")"; 
     235    }  
     236    else return "No such statistic for this overlay type"; 
     237  } 
     238  
    215239  /** Retrieves useful statistics about this overlay. */ 
    216240  public String getStatistics() { 
    217241    return "Marker coordinates = (" + x1 + ", " + y1 + ")"; 
    218242  } 
    219    
    220   /** Gets this object's statistics in array */ 
    221   public OverlayStat[] getStatisticsArray() { 
    222     String coords = "(" + x1 + ", " + y1 + ")"; 
    223     OverlayStat[] stats = { new OverlayStat("Coordinates", coords) }; 
    224     return stats; 
    225   } 
    226  
     243  
    227244  /** True iff this overlay has an endpoint coordinate pair. */ 
    228245  public boolean hasEndpoint() { return true; } 
  • trunk/loci/visbio/overlays/OverlayNodedObject.java

    r2623 r2653  
    3737 
    3838public abstract class OverlayNodedObject extends OverlayObject { 
     39 
     40  // -- Static Fields --  
     41   
     42  /** The names of the statistics this object reports */ 
     43  protected static String[] statTypes =  {"Bounds", "Nodes", 
     44    "Length"}; 
    3945 
    4046  // -- Constants -- 
     
    7480 
    7581  /** Radius in pixels of circle indicating a node is selected */ 
    76   protected static final float RADIUS = 7.5f; 
     82  protected static final float RADIUS = 3.0f; 
    7783   
    7884  // -- Fields -- 
     
    98104  /** Color to highlight highlighted node */ 
    99105  protected Color highlightColor; 
    100  
    101   /** The active display, used by the getData method */ 
    102   protected DisplayImpl display; 
    103106 
    104107  // -- Constructors -- 
     
    142145  } 
    143146 
     147  // -- Static methods -- 
     148 
     149  /** Returns the names of the statistics this object reports */ 
     150  public static String[] getStatTypes() { return statTypes; } 
     151 
    144152  // -- OverlayObject API methods -- 
    145    
     153 
     154  /** Returns whether this object is drawable, i.e., is of nonzero  
     155  *  size, area, length, etc.  
     156  */ 
     157  public boolean hasData() {  
     158    if (isDrawing()) return (numNodes > 0); 
     159    else return (numNodes > 1); 
     160    // NOTE: Not exactly consistent with the other overlay objects. 
     161    // You want to see 1-node objects while drawing, but  
     162    // want to delete them if after drawing is done. 
     163  } 
     164    
    146165  /** Gets VisAD data object representing this overlay. */ 
    147166  public DataImpl getData() { 
     167    if (!hasData()) return null; 
     168 
    148169    RealTupleType domain = overlay.getDomainType(); 
    149170    TupleType range = overlay.getRangeType(); 
     
    159180    int hlen = circleFilled ? len : len + 1; 
    160181    int totalSamples = maxNodes; 
    161     if (isHighlightNode()) totalSamples += hlen; 
     182    if (isHighlightNode() && !filled) totalSamples += hlen; 
    162183 
    163184    float[][] rangeSamples = new float[4][totalSamples]; 
     
    197218    // make highlight set and fill highlight range samples 
    198219    // ************************************************************** 
    199     if (isHighlightNode()) { 
     220    if (isHighlightNode() && !filled) { 
    200221      SampledSet highlightSet = null; 
    201  
    202       // scale cirlce radius 
    203       float scale; 
    204       if (display != null) scale = getScalingValue(display); 
    205       else scale = 1f; 
    206       float rad = RADIUS * scale; // 5.0 pixels wide per active display 
    207  
     222      float rad = RADIUS;  
    208223      // assemble highlight set samples 
    209224      float[][] highlightSetSamples = new float[2][hlen]; 
     
    265280      field.setSamples(rangeSamples); 
    266281    } 
    267     catch (VisADException exc) { exc.printStackTrace(); } 
     282    catch (VisADException exc) {  
     283      exc.printStackTrace();  
     284      System.out.println("isHighlightNode() = " + isHighlightNode()); 
     285      System.out.println("filled  = " + filled); 
     286      System.out.println("Thread.currentThread()" + Thread.currentThread()); 
     287      System.out.println("totalSamples = " + totalSamples); 
     288      try { 
     289        System.out.println("nodesSet.getLength = " + nodesSet.getLength());  
     290      } 
     291      catch (VisADException exc2) {exc2.printStackTrace();} 
     292      System.out.println("maxNodes = " + maxNodes);  
     293      System.out.println("numNodes = " + numNodes); 
     294      System.out.println("rangeSamples[0].length " + rangeSamples[0].length); 
     295 
     296    } 
    268297    catch (RemoteException exc) { exc.printStackTrace(); } 
    269298 
     
    283312   */ 
    284313  public DataImpl getSelectionGrid(boolean outline) { 
    285     //return super.getSelectionGrid(true); 
     314    if (!hasData()) return null; 
     315    else if (outline) return super.getSelectionGrid(outline); 
    286316 
    287317    RealTupleType domain = overlay.getDomainType(); 
    288318    TupleType range = overlay.getRangeType(); 
    289  
    290     float scl = display == null ? 1.0f : getScalingValue(display); 
    291     float delta = GLOW_WIDTH * scl; 
     319    float delta = GLOW_WIDTH; 
    292320 
    293321    /* 
     
    377405  } 
    378406 
     407  /** Returns a specific statistic of this object */ 
     408  public String getStat(String name) { 
     409    if (name.equals("Bounds")) { 
     410      return "(" + x1 + ", " + y1 + "), (" + x2 + ", " + y2 + ")"; 
     411    }  
     412    else if (name.equals("Nodes")) { 
     413      return "" + numNodes; 
     414    } 
     415    else if (name.equals("Length")) { 
     416      return "" + (float) curveLength; 
     417    } 
     418    else return "No such statistic for this overlay type"; 
     419  } 
     420 
    379421  /** Retrieves useful statistics about this overlay. */ 
    380422  public String getStatistics() { 
     
    383425      "Curve Length = " + (float) curveLength + "\n"; 
    384426  } 
    385    
    386   /** Gets this object's statistics in array */ 
    387   public OverlayStat[] getStatisticsArray() { 
    388     String bounds = "(" + x1 + ", " + y1 + ")-(" + x2 + ", " + y2 + ")"; 
    389     OverlayStat[] stats = { 
    390       new OverlayStat("Bounds", bounds), 
    391       new OverlayStat("Length (pixels, standard)", "" + curveLength), 
    392     }; 
    393  
    394     return stats; 
    395   } 
    396  
     427  
    397428  /** True iff this overlay has an endpoint coordinate pair. */ 
    398429  public boolean hasEndpoint() { return true; } 
     
    435466 
    436467  // -- Object API methods -- 
    437  
    438   /** Makes this object aware of active display.  
    439    *  The display is required to convert back and forth from pixel 
    440    *  to domain coordinates 
    441    */ 
    442   public void setActiveDisplay (DisplayImpl d) { display = d; } 
    443468 
    444469  /** Highlight a node. */  
     
    641666      maxNodes -= victims; 
    642667      nodes = newNodes; 
    643       if (numNodes == 0) overlay.removeObject(this); 
    644       if (numNodes <= 1) overlay.removeObject(this); 
    645668    } else { 
    646669      //System.out.println("deleteBetween(int, int) out of bounds error"); 
     
    662685      maxNodes = numNodes; 
    663686      nodes = newNodes; 
    664  
    665       if (numNodes == 0) { 
    666         //System.out.println("destroying " + this); 
    667         overlay.removeObject(this); 
    668       } 
    669       if (numNodes <= 1) overlay.removeObject(this); 
    670687    } 
    671688  } 
  • trunk/loci/visbio/overlays/OverlayObject.java

    r2534 r2653  
    1  
     1// 
    22// OverlayObject.java 
    33// 
     
    3232 
    3333  // -- Constants -- 
    34   protected static final float GLOW_WIDTH = 3.0f; // (pixels) 
     34   
     35  protected static final float GLOW_WIDTH = 1.0f; 
    3536 
    3637  protected static final float GLOW_ALPHA = 0.15f;  
     
    8990    overlay.setTextDrawn(false); 
    9091  } 
    91  
     92   
    9293  // -- OverlayObject API methods -- 
    9394 
     
    9899  public abstract double getDistance(double x, double y); 
    99100 
    100   /** Gets an array of OverlayStats statistics about this overlay. */ 
    101   public abstract OverlayStat[] getStatisticsArray(); 
     101  /** Returns whether this object is drawable, i.e., is of nonzero  
     102   *  size, area, length, etc.  
     103   */ 
     104  public abstract boolean hasData(); 
     105 
     106  /** Gets a specific overlay statistic */ 
     107  public abstract String getStat(String name); 
    102108 
    103109  /** Retrieves useful statistics about this overlay. */ 
  • trunk/loci/visbio/overlays/OverlayOval.java

    r2534 r2653  
    3232public class OverlayOval extends OverlayObject { 
    3333 
     34  // -- Static Fields -- 
     35   
     36  /** The names of the statistics this object reports */ 
     37  protected static String[] statTypes =  {"Coordinates", "Center", "Radius",  
     38    "Major Axis Length", "Minor Axis Length", "Area", "Eccentricity", 
     39    "Circumference (approximate)"}; 
     40  
    3441  // -- Constants -- 
    3542 
     
    8188  } 
    8289 
     90  // -- Static methods -- 
     91 
     92  /** Returns the names of the statistics this object reports */ 
     93  public static String[] getStatTypes() { return statTypes; } 
     94 
    8395  // -- OverlayObject API methods -- 
     96 
     97  /** Returns whether this object is drawable, i.e., is of nonzero  
     98   *  size, area, length, etc.  
     99   */ 
     100  public boolean hasData() { return (x1 != x2 && y1 != y2); } 
    84101 
    85102  /** Gets VisAD data object representing this overlay. */ 
    86103  public DataImpl getData() { 
    87     if (x1 == x2 || y1 == y2) return null; // don't try to render a zero-area ellipse 
     104    if (!hasData()) return null; 
     105 
    88106    RealTupleType domain = overlay.getDomainType(); 
    89107    TupleType range = overlay.getRangeType(); 
     
    147165  } 
    148166 
     167   
    149168  /** Gets a layer indicating this overlay is selected */ 
    150169  public DataImpl getSelectionGrid() { return getSelectionGrid(false); } 
     
    152171  /** Gets a layer indicating this overlay is selected */ 
    153172  public DataImpl getSelectionGrid(boolean outline) { 
    154     if (x1 == x2 || y1 == y2) return null;  
    155     // don't try to render a zero-area ellipse 
     173    if (!hasData()) return null; 
     174    else if (outline) return super.getSelectionGrid(outline); 
    156175 
    157176    RealTupleType domain = overlay.getDomainType(); 
     
    219238    else if (y > y1 && y > y2) ydist = y - Math.max(y1, y2); 
    220239    return Math.sqrt(xdist * xdist + ydist * ydist); 
     240  }  
     241 
     242  /** Returns a specific statistic of this object */ 
     243  public String getStat(String name) { 
     244    float xx = x2 - x1; 
     245    float yy = y2 - y1; 
     246    float centerX = x1 + xx / 2; 
     247    float centerY = y1 + yy / 2; 
     248    float radiusX = (xx < 0 ? -xx : xx) / 2; 
     249    float radiusY = (yy < 0 ? -yy : yy) / 2; 
     250    float major, minor; 
     251    if (radiusX > radiusY) { 
     252      major = radiusX; 
     253      minor = radiusY; 
     254    } 
     255    else { 
     256      major = radiusY; 
     257      minor = radiusX; 
     258    } 
     259    float eccen = (float) Math.sqrt(1 - (minor * minor) / (major * major)); 
     260    float area = (float) (Math.PI * major * minor); 
     261 
     262    // ellipse circumference approximation algorithm due to Ramanujan found at 
     263    // http://mathforum.org/dr.math/faq/formulas/faq.ellipse.circumference.html 
     264    float mm = (major - minor) / (major + minor); 
     265    float q = 3 * mm * mm; 
     266    float circum = (float) (Math.PI * 
     267      (major + minor) * (1 + q / (10 + Math.sqrt(4 - q)))); 
     268 
     269    if (name.equals("Coordinates")) { 
     270      return "(" + x1 + ", " + y1 + ")-(" + x2 + ", " + y2 + ")"; 
     271    }  
     272    else if (name.equals("Center")) { 
     273      return "(" + centerX + ", " + centerY + ")"; 
     274    }  
     275    else if (name.equals("Radius")) { 
     276      return "(" + radiusX + ", " + radiusY + ")"; 
     277    } 
     278    else if (name.equals("Major Axis Length")) { 
     279      return "" + major; 
     280    } 
     281    else if (name.equals("Minor Axis Length")) { 
     282      return "" + minor; 
     283    } 
     284    else if (name.equals("Area")) { 
     285      return "" + area; 
     286    } 
     287    else if (name.equals("Eccentricity")) { 
     288      return "" + eccen; 
     289    } 
     290    else if (name.equals("Circumference (approximate)")) { 
     291      return "" + circum; 
     292    } 
     293    else return "No such statistic for this overlay type"; 
    221294  } 
    222295 
     
    257330  } 
    258331 
    259  /** Gets this object's statistics in array */ 
     332  /** Gets this object's statistics in array */ 
    260333  public OverlayStat[] getStatisticsArray() { 
    261334    float xx = x2 - x1; 
  • trunk/loci/visbio/overlays/OverlayStat.java

    r2558 r2653  
    2626/** OverlayStat is an arrow wedge overlay. */ 
    2727public class OverlayStat { 
    28     
     28 
     29  // -- Static Fields -- 
     30  /** List of all OverlayObject subclasses */ 
     31  public static final String[] OVERLAY_TYPES =  
     32    {"Line", "Freeform", "Marker", "Text", 
     33    "Oval", "Box", "Arrow", "Polyline"}; 
     34 
    2935  // -- Fields -- 
    3036 
     
    3945  /** Constructs an OverlayStat object */ 
    4046  public OverlayStat(String name, String value) { 
    41         this.name = name; 
     47    this.name = name; 
    4248    this.value = value; 
    4349  } 
    4450 
    45   // -- OverlayObject API methods -- 
     51  // -- Static OverlayStat API methods -- 
     52  /** Get list of all OverlayObject subclasses */ 
     53  public static String[] getOverlayTypes() { return OVERLAY_TYPES; } 
     54 
     55  /**  
     56   * Returns statistic names for a particular class 
     57   */ 
     58  protected static String[] getStatTypes(String overlayType) { 
     59    String[] statTypes = null; 
     60    if (overlayType.equals("Arrow")) statTypes = 
     61      OverlayArrow.getStatTypes(); 
     62    else if (overlayType.equals("Box")) statTypes = 
     63      OverlayBox.getStatTypes(); 
     64    else if (overlayType.equals("Freeform")) statTypes =  
     65      OverlayFreeform.getStatTypes(); 
     66    else if (overlayType.equals("Line")) statTypes = 
     67      OverlayLine.getStatTypes(); 
     68    else if (overlayType.equals("Marker")) statTypes =  
     69      OverlayMarker.getStatTypes(); 
     70    else if (overlayType.equals("Oval")) statTypes = 
     71      OverlayOval.getStatTypes(); 
     72    else if (overlayType.equals("Polyline"))statTypes =  
     73      OverlayPolyline.getStatTypes(); 
     74    else if (overlayType.equals("Text")) statTypes = 
     75      OverlayText.getStatTypes(); 
     76    return statTypes; 
     77  } 
     78 
     79  // -- OverlayStat API methods -- 
    4680 
    4781  /** Gets the name of this OverlayStat. */ 
  • trunk/loci/visbio/overlays/OverlayText.java

    r2534 r2653  
    3232/** OverlayText is a text string overlay. */ 
    3333public class OverlayText extends OverlayObject { 
     34  // -- Static Fields --  
     35   
     36  /** The names of the statistics this object reports */ 
     37  protected static String[] statTypes =  {"Coordinates"}; 
    3438 
    3539  // -- Constructors -- 
     
    4751  } 
    4852 
     53  // -- Static methods -- 
     54 
     55  /** Returns the names of the statistics this object reports */ 
     56  public static String[] getStatTypes() {return statTypes;} 
     57 
    4958  // -- OverlayObject API methods -- 
    5059 
    5160  /** Gets VisAD data object representing this overlay. */ 
    5261  public DataImpl getData() { 
     62    if (!hasData()) return null; 
     63 
    5364    RealTupleType domain = overlay.getDomainType(); 
    5465    TupleType range = overlay.getTextRangeType(); 
     
    7283  } 
    7384 
     85  /** Returns whether this object is drawable, i.e., is of nonzero  
     86   *  size, area, length, etc.  
     87   */ 
     88  public boolean hasData() { return true; } 
     89 
    7490  /** Gets a layer indicating this object is selected */ 
    7591  public DataImpl getSelectionGrid() { return getSelectionGrid(false); } 
     
    7793  /** Gets a layer indicating this object is selected */ 
    7894  public DataImpl getSelectionGrid(boolean outline) {  
    79     if (outline) return super.getSelectionGrid(outline); 
     95    if (!hasData()) return null; 
     96    else if (outline) return super.getSelectionGrid(outline); 
    8097 
    8198    RealTupleType domain = overlay.getDomainType(); 
     
    122139  } 
    123140 
     141  /** Returns a specific statistic of this object*/ 
     142  public String getStat(String name) { 
     143    if (name.equals("Coordinates")) { 
     144      return "(" + x1 + ", " + y1 + ")"; 
     145    }  
     146    else return "No such statistic for this overlay type"; 
     147  } 
     148 
    124149  /** Retrieves useful statistics about this overlay. */ 
    125150  public String getStatistics() { 
    126151    return "Text coordinates = (" + x1 + ", " + y1 + ")"; 
    127   } 
    128  
    129   /** Gets this object's statistics in array */ 
    130   public OverlayStat[] getStatisticsArray() { 
    131     String coords = "(" + x1 + ", " + y1 + ")"; 
    132     OverlayStat[] stats = { new OverlayStat("Coordinates", coords) }; 
    133     return stats; 
    134152  } 
    135153 
  • trunk/loci/visbio/overlays/OverlayTransform.java

    r2623 r2653  
    532532 
    533533  // -- DataTransform API methods -- 
     534   
     535  public Data getData(int[] pos, int dim, DataCache cache) { 
     536    return getData(null, pos, dim, cache); 
     537  } 
    534538 
    535539  /** 
     
    540544   */ 
    541545  public Data getData(TransformLink link, int[] pos, int dim, DataCache cache) { 
     546    // note to ACS: do not assume TransformLink is null.  It may be null! 
     547    // If so, assume some reasonable defaults when computing your selection  
     548    // grids. 
     549 
     550 
    542551    if (dim != 2) { 
    543552      System.err.println(name + ": invalid dimensionality (" + dim + ")"); 
  • trunk/loci/visbio/overlays/OverlayWidget.java

    r2555 r2653  
    177177    overlayBox.addChoosableFileFilter(new ExtensionFileFilter( 
    178178      new String[] {"txt"}, "Overlay text files")); 
     179    overlayBox.setAccessory(new StatsOptionsPane()); 
    179180 
    180181    overlayXLSBox = new JFileChooser(); 
    181182    overlayXLSBox.addChoosableFileFilter(new ExtensionFileFilter( 
    182183      new String[] {"xls"}, "Overlay spreadsheet files")); 
     184    overlayXLSBox.setAccessory(new StatsOptionsPane()); 
    183185 
    184186    // current font text field 
     
    669671    } 
    670672    else if (src == save) { 
     673      StatsOptionsPane statsPane = (StatsOptionsPane) overlayBox.getAccessory(); 
     674      statsPane.loadSettings(); 
    671675      int rval = overlayBox.showSaveDialog(this); 
    672676      if (rval != JFileChooser.APPROVE_OPTION) return; 
    673677      File file = overlayBox.getSelectedFile(); 
     678      statsPane.saveSettings(); 
    674679      try { 
    675680        PrintWriter fout = new PrintWriter(new FileWriter(file)); 
     
    684689    } 
    685690    else if (src == export) { 
     691      StatsOptionsPane statsPane = (StatsOptionsPane) 
     692        overlayXLSBox.getAccessory(); 
     693      statsPane.loadSettings(); 
    686694      int rval = overlayXLSBox.showDialog(this, "Export"); 
    687695      if (rval != JFileChooser.APPROVE_OPTION) return; 
     696      // TODO save current options to OverlayManager 
    688697      File file = overlayXLSBox.getSelectedFile(); 
     698      statsPane.saveSettings(); 
    689699      try { 
    690700        FileOutputStream fout = new FileOutputStream(file); 
     
    833843  // -- Helper methods -- 
    834844 
     845 
    835846  /** Sets the font text field to reflect the currently chosen font. */ 
    836847  protected void refreshCurrentFont() { 
  • trunk/loci/visbio/overlays/PolylineTool.java

    r2623 r2653  
    144144        // if node interior, create two new polylines 
    145145        if (selectedNode > 0 && selectedNode < line.getNumNodes() - 1) { 
    146           float[][] nodes = line.getNodes(); 
    147           OverlayPolyline l1, l2; 
    148  
    149           int numNodes = line.getNumNodes(); 
    150  
    151           int numNodes1 = selectedNode; 
    152           int numNodes2 = numNodes - selectedNode - 1; 
    153           // selectedNode is an index into the node array; 
    154           float[][] n1 = new float[2][numNodes1]; 
    155           float[][] n2 = new float[2][numNodes2]; 
    156   
    157           // if a non-trivial polyline remains 'left' of deleted node 
    158           if (selectedNode > 1) { 
    159             for (int i=0; i<2; i++)  
    160               System.arraycopy(nodes[i], 0, n1[i], 0, numNodes1); 
    161  
    162             l1 = new OverlayPolyline(overlay, n1); 
    163             configureOverlay(l1); 
    164             overlay.addObject(l1); 
    165             l1.setDrawing(false); 
    166             l1.setSelected(false); 
    167           } 
    168  
    169           // if a non-trivial polyline remains 'right' of deleted node 
    170           if (selectedNode < numNodes - 1) { 
    171             for (int i=0; i<2; i++) { 
    172               System.arraycopy(nodes[i], numNodes1 + 1, n2[i], 0,  
    173                 numNodes2); 
    174             } 
    175             l2 = new OverlayPolyline(overlay, n2); 
    176             configureOverlay(l2); 
    177             overlay.addObject(l2); 
    178             l2.setDrawing(false); 
    179             l2.setSelected(false); 
    180           } 
    181  
     146          split(line, selectedNode); 
    182147          overlay.removeObject(line); 
    183148          unselect(); 
     
    337302    } 
    338303    else if (mode == EXTEND || mode == EXTEND_ON_TAIL) { 
    339       // update curve length 
    340       double lastSegLength = getLastSegmentLength(); 
    341       line.setLastNode(dx, dy); 
    342       double newLastSegLength = getLastSegmentLength(); 
    343       double delta = newLastSegLength - lastSegLength; 
    344       line.setCurveLength(line.getCurveLength() + delta);      
    345        
     304      // update curve  
     305      adjustLastNode(line, dx, dy); 
     306             
    346307      // determine if near head  
    347308      double hdist = getDistanceToNode(0, px, py, display); 
     
    358319 
    359320      if (flag == 0) { 
    360         line.setActiveDisplay(display); 
    361321        line.setHighlightNode(0, CON); 
    362322        mode = CLOSE_LOOP; 
    363323      } 
    364324      else if (flag == 1) { 
    365         line.setActiveDisplay(display); 
    366325        line.setHighlightNode(line.getNumNodes()-1, SEL); 
    367326        mode = EXTEND_ON_TAIL; 
     
    374333    else if (mode == BEG_EXTEND) { 
    375334      // update curve length 
    376       double lastSegLength = getLastSegmentLength(); 
    377       line.setLastNode(dx, dy); 
    378       double newLastSegLength = getLastSegmentLength(); 
    379       double delta = newLastSegLength - lastSegLength; 
    380       line.setCurveLength(line.getCurveLength() + delta);      
    381  
     335      adjustLastNode(line, dx, dy); 
     336       
    382337      // determine if near head  
    383338      double hdist = getDistanceToNode(0, px, py, display); 
     
    387342      // highlight first or last visible node if near 
    388343      if (hdist < THRESH) { 
    389         line.setActiveDisplay(display); 
    390344        line.setHighlightNode(line.getNumNodes()-1, CON); 
    391345        mode = CLOSE_LOOP; 
     
    430384  // -- Helper methods --  
    431385   
     386  /** Adjusts last node and curve length */ 
     387  private void adjustLastNode (OverlayPolyline line, float dx, float dy) { 
     388    double lastSegLength = getLastSegmentLength(); 
     389    line.setLastNode(dx, dy); 
     390    double newLastSegLength = getLastSegmentLength(); 
     391    double delta = newLastSegLength - lastSegLength; 
     392    line.setCurveLength(line.getCurveLength() + delta);      
     393  } 
     394   
     395  /** Splits an overlay polyline in two */ 
     396  private void split (OverlayPolyline line, int selectedNode) { 
     397    float[][] nodes = line.getNodes(); 
     398    OverlayPolyline l1, l2; 
     399 
     400    int numNodes = line.getNumNodes(); 
     401 
     402    int numNodes1 = selectedNode; 
     403    int numNodes2 = numNodes - selectedNode - 1; 
     404    // selectedNode is an index into the node array; 
     405    float[][] n1 = new float[2][numNodes1]; 
     406    float[][] n2 = new float[2][numNodes2]; 
     407 
     408    // if a non-trivial polyline remains 'left' of deleted node 
     409    if (selectedNode > 1) { 
     410      for (int i=0; i<2; i++)  
     411        System.arraycopy(nodes[i], 0, n1[i], 0, numNodes1); 
     412 
     413      l1 = new OverlayPolyline(overlay, n1); 
     414      configureOverlay(l1); 
     415      overlay.addObject(l1); 
     416      l1.setDrawing(false); 
     417      l1.setSelected(false); 
     418    } 
     419 
     420    // if a non-trivial polyline remains 'right' of deleted node 
     421    if (selectedNode < numNodes - 1) { 
     422      for (int i=0; i<2; i++) { 
     423        System.arraycopy(nodes[i], numNodes1 + 1, n2[i], 0,  
     424          numNodes2); 
     425      } 
     426      l2 = new OverlayPolyline(overlay, n2); 
     427      configureOverlay(l2); 
     428      overlay.addObject(l2); 
     429      l2.setDrawing(false); 
     430      l2.setSelected(false); 
     431    } 
     432  } 
     433 
     434 
    432435  /** Prints current mode and mouse event type: helpful for debugging */ 
    433436  private void printMode(String method) { 
     
    486489  } 
    487490 
     491  /** Releases a selected node */ 
    488492  private void unselect() { 
    489493    line = null; 
     
    491495  } 
    492496   
     497  /** Selects a particular node */ 
    493498  private void selectNode(DisplayImpl display, OverlayPolyline pln, int node) { 
    494499    line.setDrawing(false); 
     
    496501    selectedNode = node; 
    497502    pln.setHighlightNode(node, SEL); 
    498     pln.setActiveDisplay(display); 
    499503  } 
    500504   
Note: See TracChangeset for help on using the changeset viewer.