Changeset 4768 in josm
- Timestamp:
- 2012-01-07T19:17:19+01:00 (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java
r4643 r4768 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 5 import static org.openstreetmap.josm.tools.I18n.trn; 6 import static org.openstreetmap.josm.tools.I18n.marktr; 6 7 7 8 import java.awt.AWTEvent; … … 11 12 import java.awt.Graphics2D; 12 13 import java.awt.Point; 14 import java.awt.Stroke; 13 15 import java.awt.Toolkit; 14 16 import java.awt.event.AWTEventListener; … … 19 21 import java.awt.geom.GeneralPath; 20 22 import java.util.ArrayList; 23 import java.util.Arrays; 21 24 import java.util.Collection; 22 25 import java.util.Collections; … … 78 81 79 82 private Node currentBaseNode; 83 private Node previousNode; 80 84 private EastNorth currentMouseEastNorth; 85 86 private SnapHelper snapHelper = new SnapHelper(); 81 87 82 88 private Shortcut extraShortcut; 83 89 private Shortcut backspaceShortcut; 90 91 boolean snapOn; 84 92 85 93 public DrawAction(MapFrame mapFrame) { … … 117 125 } 118 126 119 /**120 * Takes the data from computeHelperLine to determine which ways/nodes should be highlighted121 * (if feature enabled). Also sets the target cursor if appropriate.122 */123 private void addHighlighting() {124 removeHighlighting();125 // if ctrl key is held ("no join"), don't highlight anything126 if (ctrl) {127 Main.map.mapView.setNewCursor(cursor, this);128 return;129 }130 131 // This happens when nothing is selected, but we still want to highlight the "target node"132 if (mouseOnExistingNode == null && getCurrentDataSet().getSelected().size() == 0133 && mousePos != null) {134 mouseOnExistingNode = Main.map.mapView.getNearestNode(mousePos, OsmPrimitive.isSelectablePredicate);135 }136 137 if (mouseOnExistingNode != null) {138 Main.map.mapView.setNewCursor(cursorJoinNode, this);139 // We also need this list for the statusbar help text140 oldHighlights.add(mouseOnExistingNode);141 if(drawTargetHighlight) {142 mouseOnExistingNode.setHighlighted(true);143 }144 return;145 }146 147 // Insert the node into all the nearby way segments148 if (mouseOnExistingWays.size() == 0) {149 Main.map.mapView.setNewCursor(cursor, this);150 return;151 }152 153 Main.map.mapView.setNewCursor(cursorJoinWay, this);154 155 // We also need this list for the statusbar help text156 oldHighlights.addAll(mouseOnExistingWays);157 if (!drawTargetHighlight) return;158 for (Way w : mouseOnExistingWays) {159 w.setHighlighted(true);160 }161 }162 163 /**164 * Removes target highlighting from primitives165 */166 private void removeHighlighting() {167 for(OsmPrimitive prim : oldHighlights) {168 prim.setHighlighted(false);169 }170 oldHighlights = new HashSet<OsmPrimitive>();171 }172 173 127 @Override public void enterMode() { 174 128 if (!isEnabled()) … … 179 133 drawTargetHighlight = Main.pref.getBoolean("draw.target-highlight", true); 180 134 wayIsFinished = false; 135 snapHelper.init(); 181 136 182 137 backspaceShortcut = Shortcut.registerShortcut("mapmode:backspace", tr("Backspace in Add mode"), KeyEvent.VK_BACK_SPACE, Shortcut.GROUP_EDIT); … … 225 180 if(Main.map == null || Main.map.mapView == null || !Main.map.mapView.isActiveLayerDrawable()) 226 181 return; 182 if (event instanceof KeyEvent) { 183 KeyEvent ke = (KeyEvent) event; 184 if (ke.getKeyCode() == KeyEvent.VK_TAB && 185 ke.getID()==KeyEvent.KEY_PRESSED) { 186 snapHelper.nextSnapMode(); 187 } 188 } // toggle angle snapping 227 189 updateKeyModifiers((InputEvent) event); 228 190 computeHelperLine(); … … 258 220 wayIsFinished = true; 259 221 Main.map.selectSelectTool(true); 260 222 snapHelper.noSnapNow(); 223 261 224 // Redraw to remove the helper line stub 262 225 computeHelperLine(); … … 265 228 } 266 229 230 private Point rightClickPressPos; 231 232 @Override 233 public void mousePressed(MouseEvent e) { 234 if (e.getButton() == MouseEvent.BUTTON3) { 235 rightClickPressPos = e.getPoint(); 236 } 237 } 238 267 239 /** 268 240 * If user clicked with the left button, add a node at the current mouse … … 272 244 */ 273 245 @Override public void mouseReleased(MouseEvent e) { 246 if (e.getButton() == MouseEvent.BUTTON3) { 247 Point curMousePos = e.getPoint(); 248 if (curMousePos.equals(rightClickPressPos)) { 249 WaySegment seg = Main.map.mapView.getNearestWaySegment(curMousePos, OsmPrimitive.isSelectablePredicate); 250 if (seg!=null) { 251 snapHelper.fixToSegment(seg); 252 computeHelperLine(); 253 redrawIfRequired(); 254 } 255 } 256 return; 257 } 274 258 if (e.getButton() != MouseEvent.BUTTON1) 275 259 return; … … 288 272 } 289 273 oldMousePos = mousePos; 290 274 291 275 // we copy ctrl/alt/shift from the event just in case our global 292 276 // AWTEvent didn't make it through the security manager. Unclear … … 309 293 } 310 294 311 if (n != null ) {295 if (n != null && !snapHelper.isActive()) { 312 296 // user clicked on node 313 297 if (selection.isEmpty() || wayIsFinished) { … … 328 312 } 329 313 } else { 330 // no node found in clicked area 331 n = new Node(Main.map.mapView.getLatLon(e.getX(), e.getY())); 314 EastNorth newEN; 315 if (n!=null) { 316 EastNorth foundPoint = n.getEastNorth(); 317 // project found node to snapping line 318 newEN = snapHelper.getSnapPoint(foundPoint); 319 if (foundPoint.distance(newEN) > 1e-4) { 320 n = new Node(newEN); // point != projected, so we create new node 321 newNode = true; 322 } 323 } else { // n==null, no node found in clicked area 324 EastNorth mouseEN = Main.map.mapView.getEastNorth(e.getX(), e.getY()); 325 newEN = snapOn ? snapHelper.getSnapPoint(mouseEN) : mouseEN; 326 n = new Node(newEN); //create node at clicked point 327 newNode = true; 328 } 329 snapHelper.unsetFixedMode(); 330 } 331 332 if (newNode) { 332 333 if (n.getCoor().isOutSideWorld()) { 333 334 JOptionPane.showMessageDialog( … … 339 340 return; 340 341 } 341 newNode = true;342 343 342 cmds.add(new AddCommand(n)); 344 343 345 344 if (!ctrl) { 346 // Insert the node into all the nearby way segments 347 List<WaySegment> wss = Main.map.mapView.getNearestWaySegments(e.getPoint(), OsmPrimitive.isSelectablePredicate); 348 Map<Way, List<Integer>> insertPoints = new HashMap<Way, List<Integer>>(); 349 for (WaySegment ws : wss) { 350 List<Integer> is; 351 if (insertPoints.containsKey(ws.way)) { 352 is = insertPoints.get(ws.way); 353 } else { 354 is = new ArrayList<Integer>(); 355 insertPoints.put(ws.way, is); 345 // Insert the node into all the nearby way segments 346 List<WaySegment> wss = Main.map.mapView.getNearestWaySegments( 347 Main.map.mapView.getPoint(n), OsmPrimitive.isSelectablePredicate); 348 insertNodeIntoAllNearbySegments(wss, n, newSelection, cmds, replacedWays, reuseWays); 356 349 } 357 358 is.add(ws.lowerIndex); 359 } 360 361 Set<Pair<Node,Node>> segSet = new HashSet<Pair<Node,Node>>(); 362 363 for (Map.Entry<Way, List<Integer>> insertPoint : insertPoints.entrySet()) { 364 Way w = insertPoint.getKey(); 365 List<Integer> is = insertPoint.getValue(); 366 367 Way wnew = new Way(w); 368 369 pruneSuccsAndReverse(is); 370 for (int i : is) { 371 segSet.add( 372 Pair.sort(new Pair<Node,Node>(w.getNode(i), w.getNode(i+1)))); 373 } 374 for (int i : is) { 375 wnew.addNode(i + 1, n); 376 } 377 378 // If ALT is pressed, a new way should be created and that new way should get 379 // selected. This works everytime unless the ways the nodes get inserted into 380 // are already selected. This is the case when creating a self-overlapping way 381 // but pressing ALT prevents this. Therefore we must de-select the way manually 382 // here so /only/ the new way will be selected after this method finishes. 383 if(alt) { 384 newSelection.add(insertPoint.getKey()); 385 } 386 387 cmds.add(new ChangeCommand(insertPoint.getKey(), wnew)); 388 replacedWays.add(insertPoint.getKey()); 389 reuseWays.add(wnew); 390 } 391 392 adjustNode(segSet, n); 393 } 394 } 395 350 } 351 // now "n" is newly created or reused node that shoud be added to some way 352 396 353 // This part decides whether or not a "segment" (i.e. a connection) is made to an 397 354 // existing node. … … 543 500 redrawIfRequired(); 544 501 } 502 503 private void insertNodeIntoAllNearbySegments(List<WaySegment> wss, Node n, Collection<OsmPrimitive> newSelection, Collection<Command> cmds, ArrayList<Way> replacedWays, ArrayList<Way> reuseWays) { 504 Map<Way, List<Integer>> insertPoints = new HashMap<Way, List<Integer>>(); 505 for (WaySegment ws : wss) { 506 List<Integer> is; 507 if (insertPoints.containsKey(ws.way)) { 508 is = insertPoints.get(ws.way); 509 } else { 510 is = new ArrayList<Integer>(); 511 insertPoints.put(ws.way, is); 512 } 513 514 is.add(ws.lowerIndex); 515 } 516 517 Set<Pair<Node,Node>> segSet = new HashSet<Pair<Node,Node>>(); 518 519 for (Map.Entry<Way, List<Integer>> insertPoint : insertPoints.entrySet()) { 520 Way w = insertPoint.getKey(); 521 List<Integer> is = insertPoint.getValue(); 522 523 Way wnew = new Way(w); 524 525 pruneSuccsAndReverse(is); 526 for (int i : is) { 527 segSet.add( 528 Pair.sort(new Pair<Node,Node>(w.getNode(i), w.getNode(i+1)))); 529 } 530 for (int i : is) { 531 wnew.addNode(i + 1, n); 532 } 533 534 // If ALT is pressed, a new way should be created and that new way should get 535 // selected. This works everytime unless the ways the nodes get inserted into 536 // are already selected. This is the case when creating a self-overlapping way 537 // but pressing ALT prevents this. Therefore we must de-select the way manually 538 // here so /only/ the new way will be selected after this method finishes. 539 if(alt) { 540 newSelection.add(insertPoint.getKey()); 541 } 542 543 cmds.add(new ChangeCommand(insertPoint.getKey(), wnew)); 544 replacedWays.add(insertPoint.getKey()); 545 reuseWays.add(wnew); 546 } 547 548 adjustNode(segSet, n); 549 } 550 545 551 546 552 /** … … 642 648 Collection<OsmPrimitive> selection = getCurrentDataSet().getSelected(); 643 649 644 Node selectedNode = null;645 Way selectedWay = null;646 650 Node currentMouseNode = null; 647 651 mouseOnExistingNode = null; … … 675 679 } 676 680 681 determineCurrentBaseNodeAndPreviousNode(selection); 682 if (previousNode == null) snapHelper.noSnapNow(); 683 684 if (currentBaseNode == null || currentBaseNode == currentMouseNode) 685 return; // Don't create zero length way segments. 686 687 // find out the distance, in metres, between the base point and the mouse cursor 688 LatLon mouseLatLon = mv.getProjection().eastNorth2latlon(currentMouseEastNorth); 689 distance = currentBaseNode.getCoor().greatCircleDistance(mouseLatLon); 690 691 double hdg = Math.toDegrees(currentBaseNode.getEastNorth() 692 .heading(currentMouseEastNorth)); 693 if (previousNode != null) { 694 angle = hdg - Math.toDegrees(previousNode.getEastNorth() 695 .heading(currentBaseNode.getEastNorth())); 696 angle += angle < 0 ? 360 : 0; 697 } 698 699 if (snapOn) snapHelper.checkAngleSnapping(currentMouseEastNorth,angle); 700 701 Main.map.statusLine.setAngle(angle); 702 Main.map.statusLine.setHeading(hdg); 703 Main.map.statusLine.setDist(distance); 704 // Now done in redrawIfRequired() 705 //updateStatusLine(); 706 } 707 708 709 /** 710 * Helper function that sets fields currentBaseNode and previousNode 711 * @param selection 712 * uses also lastUsedNode field 713 */ 714 private void determineCurrentBaseNodeAndPreviousNode(Collection<OsmPrimitive> selection) { 715 Node selectedNode = null; 716 Way selectedWay = null; 677 717 for (OsmPrimitive p : selection) { 678 718 if (p instanceof Node) { … … 684 724 } 685 725 } 726 // we are here, if not more than 1 way or node is selected, 686 727 687 728 // the node from which we make a connection 688 729 currentBaseNode = null; 689 NodepreviousNode = null;730 previousNode = null; 690 731 691 732 if (selectedNode == null) { … … 701 742 currentBaseNode = selectedNode; 702 743 } else if (!selectedWay.isDeleted()) { // fix #7118 703 if (selectedNode == selectedWay.getNode(0) || selectedNode == selectedWay.getNode(selectedWay.getNodesCount()-1)){744 if (selectedNode == selectedWay.getNode(0)){ 704 745 currentBaseNode = selectedNode; 705 } 706 } 707 708 if (currentBaseNode == null || currentBaseNode == currentMouseNode) 709 return; // Don't create zero length way segments. 710 711 // find out the distance, in metres, between the base point and the mouse cursor 712 LatLon mouseLatLon = mv.getProjection().eastNorth2latlon(currentMouseEastNorth); 713 distance = currentBaseNode.getCoor().greatCircleDistance(mouseLatLon); 714 715 double hdg = Math.toDegrees(currentBaseNode.getEastNorth() 716 .heading(currentMouseEastNorth)); 717 if (previousNode != null) { 718 angle = hdg - Math.toDegrees(previousNode.getEastNorth() 719 .heading(currentBaseNode.getEastNorth())); 720 angle += angle < 0 ? 360 : 0; 721 } 722 723 Main.map.statusLine.setAngle(angle); 724 Main.map.statusLine.setHeading(hdg); 725 Main.map.statusLine.setDist(distance); 726 // Now done in redrawIfRequired() 727 //updateStatusLine(); 728 } 746 if (selectedWay.getNodesCount()>1) previousNode = selectedWay.getNode(1); 747 } 748 if (selectedNode == selectedWay.lastNode()) { 749 currentBaseNode = selectedNode; 750 if (selectedWay.getNodesCount()>1) 751 previousNode = selectedWay.getNode(selectedWay.getNodesCount()-2); 752 } 753 } 754 } 755 729 756 730 757 /** … … 735 762 return; 736 763 mousePos = e.getPoint(); 764 snapHelper.noSnapNow(); 737 765 Main.map.mapView.repaint(); 738 766 } … … 742 770 * <code>null</code> otherwise. 743 771 */ 744 public Way getWayForNode(Node n) {772 public static Way getWayForNode(Node n) { 745 773 Way way = null; 746 774 for (Way w : Utils.filteredCollection(n.getReferrers(), Way.class)) { … … 853 881 return a * d - b * c; 854 882 } 855 883 /** 884 * Takes the data from computeHelperLine to determine which ways/nodes should be highlighted 885 * (if feature enabled). Also sets the target cursor if appropriate. 886 */ 887 private void addHighlighting() { 888 removeHighlighting(); 889 // if ctrl key is held ("no join"), don't highlight anything 890 if (ctrl) { 891 Main.map.mapView.setNewCursor(cursor, this); 892 return; 893 } 894 895 // This happens when nothing is selected, but we still want to highlight the "target node" 896 if (mouseOnExistingNode == null && getCurrentDataSet().getSelected().size() == 0 897 && mousePos != null) { 898 mouseOnExistingNode = Main.map.mapView.getNearestNode(mousePos, OsmPrimitive.isSelectablePredicate); 899 } 900 901 if (mouseOnExistingNode != null) { 902 Main.map.mapView.setNewCursor(cursorJoinNode, this); 903 // We also need this list for the statusbar help text 904 oldHighlights.add(mouseOnExistingNode); 905 if(drawTargetHighlight) { 906 mouseOnExistingNode.setHighlighted(true); 907 } 908 return; 909 } 910 911 // Insert the node into all the nearby way segments 912 if (mouseOnExistingWays.size() == 0) { 913 Main.map.mapView.setNewCursor(cursor, this); 914 return; 915 } 916 917 Main.map.mapView.setNewCursor(cursorJoinWay, this); 918 919 // We also need this list for the statusbar help text 920 oldHighlights.addAll(mouseOnExistingWays); 921 if (!drawTargetHighlight) return; 922 for (Way w : mouseOnExistingWays) { 923 w.setHighlighted(true); 924 } 925 } 926 927 /** 928 * Removes target highlighting from primitives 929 */ 930 private void removeHighlighting() { 931 for(OsmPrimitive prim : oldHighlights) { 932 prim.setHighlighted(false); 933 } 934 oldHighlights = new HashSet<OsmPrimitive>(); 935 } 936 856 937 public void paint(Graphics2D g, MapView mv, Bounds box) { 857 if (!drawHelperLine || wayIsFinished || shift) return;858 859 938 // sanity checks 860 939 if (Main.map.mapView == null) return; … … 866 945 // don't draw line if mouse is outside window 867 946 if (!Main.map.mapView.getBounds().contains(mousePos)) return; 868 947 869 948 Graphics2D g2 = g; 870 g2.setColor(selectedColor); 871 g2.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 949 if (snapOn) snapHelper.draw(g2,mv); 950 if (!drawHelperLine || wayIsFinished || shift) return; 951 952 if (!snapHelper.isActive()) { // else use color and stoke from snapHelper.draw 953 g2.setColor(selectedColor); 954 g2.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 955 } 872 956 GeneralPath b = new GeneralPath(); 873 957 Point p1=mv.getPoint(currentBaseNode); … … 933 1017 rv += " " + tr("Continue way from last node."); 934 1018 } 1019 if (snapOn) { 1020 rv += " "+ tr("Angle snapping ON."); 1021 } 935 1022 } 936 1023 … … 976 1063 Main.unregisterActionShortcut(extraShortcut); 977 1064 } 978 1065 979 1066 public static class BackSpaceAction extends AbstractAction { 980 1067 … … 1002 1089 } 1003 1090 1091 private class SnapHelper { 1092 private boolean active; // snapping is activa for current mouse position 1093 private boolean fixed; // snap angle is fixed 1094 private boolean absoluteFix; // snap angle is absolute 1095 EastNorth dir2; 1096 EastNorth projected; 1097 String labelText; 1098 double lastAngle; 1099 1100 double snapAngles[]; 1101 double snapAngleTolerance; 1102 1103 double pe,pn; // (pe,pn) - direction of snapping line 1104 double e0,n0; // (e0,n0) - origin of snapping line 1105 1106 final String fixFmt="%d "+tr("FIX"); 1107 Color snapHelperColor; 1108 private Stroke normalStroke; 1109 private Stroke helperStroke; 1110 1111 private void init() { 1112 snapOn=false; 1113 fixed=false; absoluteFix=false; 1114 1115 Collection<String> angles = Main.pref.getCollection("draw.anglesnap.angles", 1116 Arrays.asList("0","30","45","60","90","120","135","150","210","225","240","270","300","315","330")); 1117 1118 snapAngles = new double[angles.size()]; 1119 int i=0; 1120 for (String s: angles) { 1121 try { 1122 snapAngles[i] = Double.parseDouble(s); 1123 } catch (NumberFormatException e) { 1124 System.err.println("Warning: incorrect number in draw.anglesnap.angles preferences: "+s); 1125 snapAngles[i]=0; 1126 } 1127 i++; 1128 } 1129 snapAngleTolerance = Main.pref.getDouble("draw.anglesnap.tolerance", 5.0); 1130 1131 normalStroke = new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); 1132 snapHelperColor = Main.pref.getColor(marktr("draw angle snap"), Color.ORANGE); 1133 1134 float dash1[] = { 4.0f }; 1135 helperStroke = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, 1136 BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f); 1137 1138 } 1139 1140 private void noSnapNow() { 1141 active=false; 1142 dir2=null; projected=null; 1143 labelText=null; 1144 } 1145 1146 private void draw(Graphics2D g2, MapView mv) { 1147 if (!active) return; 1148 Point p1=mv.getPoint(currentBaseNode); 1149 Point p2=mv.getPoint(dir2); 1150 Point p3=mv.getPoint(projected); 1151 GeneralPath b; 1152 1153 g2.setColor(snapHelperColor); 1154 g2.setStroke(helperStroke); 1155 1156 b = new GeneralPath(); 1157 if (absoluteFix) { 1158 b.moveTo(p2.x,p2.y); 1159 b.lineTo(2*p1.x-p2.x,2*p1.y-p2.y); // bi-directional line 1160 } else { 1161 b.moveTo(p2.x,p2.y); 1162 b.lineTo(p3.x,p3.y); 1163 } 1164 g2.draw(b); 1165 1166 g2.setColor(selectedColor); 1167 g2.setStroke(normalStroke); 1168 b = new GeneralPath(); 1169 b.moveTo(p1.x,p1.y); 1170 b.lineTo(p3.x,p3.y); 1171 g2.draw(b); 1172 1173 g2.drawString(labelText, p3.x-5, p3.y+20); 1174 g2.setStroke(normalStroke); 1175 g2.drawOval(p3.x-5, p3.y-5, 10, 10); // projected point 1176 1177 g2.setColor(snapHelperColor); 1178 g2.setStroke(helperStroke); 1179 1180 } 1181 1182 private double getAngleDelta(double a, double b) { 1183 double delta = Math.abs(a-b); 1184 if (delta>180) return 360-delta; else return delta; 1185 } 1186 1187 /* If mouse position is close to line at 15-30-45-... angle, remembers this direction 1188 */ 1189 private void checkAngleSnapping(EastNorth currentEN, double angle) { 1190 if (!absoluteFix && previousNode==null) return; 1191 1192 double nearestAngle; 1193 if (fixed) { 1194 nearestAngle = lastAngle; // if direction is fixed 1195 active=true; 1196 } else { 1197 nearestAngle = getNearestAngle(angle); 1198 lastAngle = nearestAngle; 1199 active = Math.abs(nearestAngle-180)>1e-3 && getAngleDelta(nearestAngle,angle)<snapAngleTolerance; 1200 } 1201 1202 if (active) { 1203 double de,dn,l, phi; 1204 1205 EastNorth p0 = currentBaseNode.getEastNorth(); 1206 e0=p0.east(); n0=p0.north(); 1207 1208 if (fixed) { 1209 if (absoluteFix) labelText = "="; 1210 else labelText = String.format(fixFmt, (int) nearestAngle); 1211 } else labelText = String.format("%d", (int) nearestAngle); 1212 1213 if (absoluteFix) { 1214 de=0; dn=1; 1215 } else { 1216 EastNorth prev = previousNode.getEastNorth(); 1217 de = e0-prev.east(); 1218 dn = n0-prev.north(); 1219 l=Math.hypot(de, dn); 1220 if (Math.abs(l)<1e-4) { noSnapNow(); return; } 1221 de/=l; dn/=l; 1222 } 1223 1224 phi=nearestAngle*Math.PI/180; 1225 // (pe,pn) - direction of snapping line 1226 pe = de*Math.cos(phi) + dn*Math.sin(phi); 1227 pn = -de*Math.sin(phi) + dn*Math.cos(phi); 1228 double scale = 20*Main.map.mapView.getDist100Pixel(); 1229 dir2 = new EastNorth( e0+scale*pe, n0+scale*pn); 1230 getSnapPoint(currentEN); 1231 } else { 1232 noSnapNow(); 1233 } 1234 } 1235 1236 private EastNorth getSnapPoint(EastNorth p) { 1237 if (!active) return p; 1238 double de=p.east()-e0; 1239 double dn=p.north()-n0; 1240 double l = de*pe+dn*pn; 1241 if (!absoluteFix && l<1e-5) {active=false; return p; } // do not go backward! 1242 return projected = new EastNorth(e0+l*pe, n0+l*pn); 1243 } 1244 1245 private void unsetFixedMode() { 1246 fixed=false; absoluteFix=false; 1247 lastAngle=0; 1248 active=false; 1249 } 1250 1251 private void nextSnapMode() { 1252 if (snapOn) { 1253 // turn off snapping if we are in fixed mode or no actile snapping line exist 1254 if (fixed || !active) { snapOn=false; unsetFixedMode(); } 1255 else if (active) { fixed=true; } 1256 } else { 1257 snapOn=true; 1258 unsetFixedMode(); 1259 } 1260 } 1261 1262 private boolean isActive() { 1263 return active; 1264 } 1265 1266 private double getNearestAngle(double angle) { 1267 double delta,minDelta=1e5, bestAngle=0.0; 1268 for (int i=0; i<snapAngles.length; i++) { 1269 delta = getAngleDelta(angle,snapAngles[i]); 1270 if (delta<minDelta) { 1271 minDelta=delta; 1272 bestAngle=snapAngles[i]; 1273 } 1274 } 1275 if (Math.abs(bestAngle-360)<1e-3) bestAngle=0; 1276 return bestAngle; 1277 } 1278 1279 private void fixToSegment(WaySegment seg) { 1280 if (seg==null) return; 1281 double hdg = seg.getFirstNode().getEastNorth().heading(seg.getSecondNode().getEastNorth()); 1282 hdg=Math.toDegrees(hdg); 1283 if (hdg<0) hdg+=360; 1284 if (hdg>360) hdg=hdg-360; 1285 fixed=true; 1286 absoluteFix=true; 1287 lastAngle=hdg; 1288 } 1289 } 1004 1290 }
Note:
See TracChangeset
for help on using the changeset viewer.