- Timestamp:
- 2012-02-16T15:37:24+01:00 (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java
r4924 r4954 334 334 WaySegment seg = Main.map.mapView.getNearestWaySegment(curMousePos, OsmPrimitive.isSelectablePredicate); 335 335 if (seg!=null) { 336 snapHelper. fixToSegment(seg);336 snapHelper.setBaseSegment(seg); 337 337 computeHelperLine(); 338 338 redrawIfRequired(); … … 772 772 773 773 774 double hdg = Math.toDegrees(currentBaseNode.getEastNorth()774 double curHdg = Math.toDegrees(currentBaseNode.getEastNorth() 775 775 .heading(currentMouseEastNorth)); 776 double baseHdg=-1; 776 777 if (previousNode != null) { 777 angle = hdg -Math.toDegrees(previousNode.getEastNorth()778 baseHdg = Math.toDegrees(previousNode.getEastNorth() 778 779 .heading(currentBaseNode.getEastNorth())); 779 angle += angle < 0 ? 360 : 0; 780 } 781 782 snapHelper.checkAngleSnapping(currentMouseEastNorth,angle); 783 if (!snapHelper.isActive()) { 784 // find out the distance, in metres, between the base point and the mouse cursor 785 LatLon mouseLatLon = mv.getProjection().eastNorth2latlon(currentMouseEastNorth); 786 distance = currentBaseNode.getCoor().greatCircleDistance(mouseLatLon); 787 showStatusInfo(angle, hdg, distance); 788 } // elsewhere status ar was filled by snapHelper 780 } 781 782 snapHelper.checkAngleSnapping(currentMouseEastNorth,baseHdg, curHdg); 783 784 // status bar was filled by snapHelper 789 785 790 786 // Now done in redrawIfRequired() … … 1197 1193 boolean snapOn; // snapping is turned on 1198 1194 1199 private boolean active; // snapping is activ afor current mouse position1195 private boolean active; // snapping is active for current mouse position 1200 1196 private boolean fixed; // snap angle is fixed 1201 private boolean absoluteFix; // snap angle is absolute 1197 private boolean absoluteFix; // snap angle is absolute 1202 1198 1203 1199 private boolean drawConstructionGeometry; 1204 1200 private boolean showProjectedPoint; 1205 1201 private boolean showAngle; 1202 1203 private boolean snapToProjections; 1206 1204 1207 1205 EastNorth dir2; … … 1209 1207 String labelText; 1210 1208 double lastAngle; 1209 double customBaseHeading=-1; // angle of base line, if not last segment) 1210 private EastNorth segmentPoint1; // remembered first point of base segment 1211 private EastNorth segmentPoint2; // remembered second point of base segment 1212 private EastNorth projectionSource; // point that we are projecting to the line 1211 1213 1212 1214 double snapAngles[]; … … 1218 1220 final String fixFmt="%d "+tr("FIX"); 1219 1221 Color snapHelperColor; 1222 private Color highlightColor; 1223 1220 1224 private Stroke normalStroke; 1221 1225 private Stroke helperStroke; 1226 private Stroke highlightStroke; 1222 1227 1223 1228 JCheckBoxMenuItem checkBox; … … 1229 1234 1230 1235 Collection<String> angles = Main.pref.getCollection("draw.anglesnap.angles", 1231 Arrays.asList("0","30","45","60","90","120","135","150" ));1236 Arrays.asList("0","30","45","60","90","120","135","150","180")); 1232 1237 1233 1238 snapAngles = new double[2*angles.size()]; … … 1246 1251 drawConstructionGeometry = Main.pref.getBoolean("draw.anglesnap.drawConstructionGeometry", true); 1247 1252 showProjectedPoint = Main.pref.getBoolean("draw.anglesnap.drawProjectedPoint", true); 1253 snapToProjections = Main.pref.getBoolean("draw.anglesnap.projectionsnap", true); 1254 1248 1255 showAngle = Main.pref.getBoolean("draw.anglesnap.showAngle", true); 1249 1256 1250 1257 normalStroke = new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); 1251 1258 snapHelperColor = Main.pref.getColor(marktr("draw angle snap"), Color.ORANGE); 1259 1260 highlightColor = Main.pref.getColor(marktr("draw angle snap highlight"), new Color(Color.ORANGE.getRed(),Color.ORANGE.getGreen(),Color.ORANGE.getBlue(),128)); 1261 highlightStroke = new BasicStroke(10, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); 1252 1262 1253 1263 float dash1[] = { 4.0f }; … … 1287 1297 g2.draw(b); 1288 1298 } 1289 1299 if (projectionSource!=null) { 1300 g2.setColor(snapHelperColor); 1301 g2.setStroke(helperStroke); 1302 b = new GeneralPath(); 1303 b.moveTo(p3.x,p3.y); 1304 Point pp=mv.getPoint(projectionSource); 1305 b.lineTo(pp.x,pp.y); 1306 g2.draw(b); 1307 } 1308 1309 1310 if (customBaseHeading>=0) { 1311 g2.setColor(highlightColor); 1312 g2.setStroke(highlightStroke); 1313 b = new GeneralPath(); 1314 Point pp1=mv.getPoint(segmentPoint1); 1315 Point pp2=mv.getPoint(segmentPoint2); 1316 b.moveTo(pp1.x,pp1.y); 1317 b.lineTo(pp2.x,pp2.y); 1318 g2.draw(b); 1319 } 1320 1321 1290 1322 g2.setColor(selectedColor); 1291 1323 g2.setStroke(normalStroke); … … 1308 1340 /* If mouse position is close to line at 15-30-45-... angle, remembers this direction 1309 1341 */ 1310 public void checkAngleSnapping(EastNorth currentEN, double angle) { 1311 if (!snapOn) return; 1312 if (!absoluteFix && previousNode==null) return; 1342 public void checkAngleSnapping(EastNorth currentEN, double baseHeading, double curHeading) { 1343 EastNorth p0 = currentBaseNode.getEastNorth(); 1344 EastNorth snapPoint = currentEN; 1345 double angle = -1; 1313 1346 1314 double nearestAngle; 1315 if (fixed) { 1316 nearestAngle = lastAngle; // if direction is fixed 1317 active=true; 1318 } else { 1319 nearestAngle = getNearestAngle(angle); 1320 lastAngle = nearestAngle; 1321 active = Math.abs(nearestAngle-180)>1e-3 && getAngleDelta(nearestAngle,angle)<snapAngleTolerance; 1322 } 1347 double activeBaseHeading = (customBaseHeading>=0)? customBaseHeading : baseHeading; 1323 1348 1324 if (active) { 1325 double de,dn,l, phi; 1326 1327 EastNorth p0 = currentBaseNode.getEastNorth(); 1328 e0=p0.east(); n0=p0.north(); 1349 if (snapOn && (activeBaseHeading>=0)) { 1350 angle = curHeading - activeBaseHeading; 1351 if (angle < 0) angle+=360; 1352 if (angle > 360) angle=0; 1329 1353 1330 if (showAngle) { 1331 if (fixed) { 1332 if (absoluteFix) labelText = "="; 1333 else labelText = String.format(fixFmt, (int) nearestAngle); 1334 } else labelText = String.format("%d", (int) nearestAngle); 1354 double nearestAngle; 1355 if (fixed) { 1356 nearestAngle = lastAngle; // if direction is fixed use previous angle 1357 active = true; 1335 1358 } else { 1336 if (fixed) { 1337 if (absoluteFix) labelText = "="; 1338 else labelText = String.format(tr("FIX"),0); 1339 } else labelText=""; 1340 } 1341 1342 if (absoluteFix) { 1343 de=0; dn=1; 1359 nearestAngle = getNearestAngle(angle); 1360 if (getAngleDelta(nearestAngle, angle) < snapAngleTolerance) { 1361 active = (customBaseHeading>=0)? true : Math.abs(nearestAngle - 180) > 1e-3; 1362 // if angle is to previous segment, exclude 180 degrees 1363 lastAngle = nearestAngle; 1364 } else active=false; 1365 } 1366 1367 if (active) { 1368 double de, dn, l, phi; 1369 e0 = p0.east(); 1370 n0 = p0.north(); 1371 buildLabelText(nearestAngle); 1372 1373 phi = (nearestAngle + activeBaseHeading) * Math.PI / 180; 1374 // (pe,pn) - direction of snapping line 1375 pe = Math.sin(phi); 1376 pn = Math.cos(phi); 1377 double scale = 20 * Main.map.mapView.getDist100Pixel(); 1378 dir2 = new EastNorth(e0 + scale * pe, n0 + scale * pn); 1379 snapPoint = getSnapPoint(currentEN); 1344 1380 } else { 1345 EastNorth prev = previousNode.getEastNorth(); 1346 de = e0-prev.east(); 1347 dn = n0-prev.north(); 1348 l=Math.hypot(de, dn); 1349 if (Math.abs(l)<1e-4) { noSnapNow(); return; } 1350 de/=l; dn/=l; 1351 } 1352 1353 phi=nearestAngle*Math.PI/180; 1354 // (pe,pn) - direction of snapping line 1355 pe = de*Math.cos(phi) + dn*Math.sin(phi); 1356 pn = -de*Math.sin(phi) + dn*Math.cos(phi); 1357 double scale = 20*Main.map.mapView.getDist100Pixel(); 1358 dir2 = new EastNorth( e0+scale*pe, n0+scale*pn); 1359 EastNorth snapPoint = getSnapPoint(currentEN); 1360 1361 // find out the distance, in metres, between the base point and projected point 1362 LatLon mouseLatLon = Main.map.mapView.getProjection().eastNorth2latlon(snapPoint); 1363 double distance = currentBaseNode.getCoor().greatCircleDistance(mouseLatLon); 1364 double hdg = Math.toDegrees(p0.heading(snapPoint)); 1365 if (previousNode != null) { 1366 angle = hdg - Math.toDegrees(previousNode.getEastNorth().heading(p0)); 1367 angle += angle < 0 ? 360 : 0; 1368 if (Math.abs(angle-360)<1e-4) angle=0; 1369 } 1370 1371 showStatusInfo(angle, hdg, distance); 1372 } else { 1373 noSnapNow(); 1374 } 1381 noSnapNow(); 1382 } 1383 } 1384 1385 // find out the distance, in metres, between the base point and projected point 1386 LatLon mouseLatLon = Main.map.mapView.getProjection().eastNorth2latlon(snapPoint); 1387 double distance = currentBaseNode.getCoor().greatCircleDistance(mouseLatLon); 1388 double hdg = Math.toDegrees(p0.heading(snapPoint)); 1389 // heading of segment from current to calculated point, not to mouse position 1390 1391 if (baseHeading >=0 ) { // there is previous line segment with some heading 1392 angle = hdg - baseHeading; 1393 if (angle < 0) angle+=360; 1394 if (angle > 360) angle=0; 1395 } 1396 showStatusInfo(angle, hdg, distance); 1397 } 1398 1399 private void buildLabelText(double nearestAngle) { 1400 if (showAngle) { 1401 if (fixed) { 1402 if (absoluteFix) { 1403 labelText = "="; 1404 } else { 1405 labelText = String.format(fixFmt, (int) nearestAngle); 1406 } 1407 } else { 1408 labelText = String.format("%d", (int) nearestAngle); 1409 } 1410 } else { 1411 if (fixed) { 1412 if (absoluteFix) { 1413 labelText = "="; 1414 } else { 1415 labelText = String.format(tr("FIX"), 0); 1416 } 1417 } else { 1418 labelText = ""; 1419 } 1420 } 1375 1421 } 1376 1422 … … 1380 1426 double dn=p.north()-n0; 1381 1427 double l = de*pe+dn*pn; 1382 if (!absoluteFix && l<1e-5) {active=false; return p; } // do not go backward! 1428 double delta = Main.map.mapView.getDist100Pixel()/20; 1429 if (!absoluteFix && l<delta) {active=false; return p; } // do not go backward! 1430 1431 projectionSource=null; 1432 if (snapToProjections) { 1433 DataSet ds = getCurrentDataSet(); 1434 Collection<Way> selectedWays = ds.getSelectedWays(); 1435 if (selectedWays.size()==1) { 1436 Way w = selectedWays.iterator().next(); 1437 for (Node n: w.getNodes()) { 1438 EastNorth en=n.getEastNorth(); 1439 double l1 = (en.east()-e0)*pe+(en.north()-n0)*pn; 1440 if (Math.abs(l1-l) < delta) { 1441 l=l1; 1442 projectionSource = en; 1443 break; 1444 } 1445 } 1446 } 1447 } 1383 1448 return projected = new EastNorth(e0+l*pe, n0+l*pn); 1384 1449 } … … 1391 1456 } 1392 1457 1393 public void fixToSegment(WaySegment seg) {1458 public void setBaseSegment(WaySegment seg) { 1394 1459 if (seg==null) return; 1395 double hdg = seg.getFirstNode().getEastNorth().heading(seg.getSecondNode().getEastNorth()); 1460 segmentPoint1=seg.getFirstNode().getEastNorth(); 1461 segmentPoint2=seg.getSecondNode().getEastNorth(); 1462 1463 double hdg = segmentPoint1.heading(segmentPoint2); 1396 1464 hdg=Math.toDegrees(hdg); 1397 1465 if (hdg<0) hdg+=360; 1398 if (hdg>360) hdg =hdg-360;1399 fixed=true;1400 absoluteFix=true;1401 lastAngle=hdg;1466 if (hdg>360) hdg-=360; 1467 //fixed=true; 1468 //absoluteFix=true; 1469 customBaseHeading=hdg; 1402 1470 } 1403 1471 … … 1412 1480 } 1413 1481 checkBox.setState(snapOn); 1482 customBaseHeading=-1; 1414 1483 } 1415 1484 … … 1417 1486 snapOn = true; 1418 1487 checkBox.setState(snapOn); 1488 customBaseHeading=-1; 1419 1489 unsetFixedMode(); 1420 1490 } … … 1423 1493 snapOn = !snapOn; 1424 1494 checkBox.setState(snapOn); 1495 customBaseHeading=-1; 1425 1496 unsetFixedMode(); 1426 1497 } … … 1468 1539 1469 1540 MouseListener anglePopupListener = new PopupMenuLauncher( new JPopupMenu() { 1470 { 1471 add(new JCheckBoxMenuItem(new AbstractAction(tr("Show helper geometry")){ 1541 JCheckBoxMenuItem helperCb = new JCheckBoxMenuItem(new AbstractAction(tr("Show helper geometry")){ 1472 1542 public void actionPerformed(ActionEvent e) { 1473 1543 boolean sel=((JCheckBoxMenuItem) e.getSource()).getState(); … … 1477 1547 init(); enableSnapping(); 1478 1548 } 1479 })); 1549 }); 1550 JCheckBoxMenuItem projectionCb = new JCheckBoxMenuItem(new AbstractAction(tr("Snap to node projections")){ 1551 public void actionPerformed(ActionEvent e) { 1552 boolean sel=((JCheckBoxMenuItem) e.getSource()).getState(); 1553 Main.pref.put("draw.anglesnap.projectionsnap", sel); 1554 init(); enableSnapping(); 1555 } 1556 }); 1557 { 1558 helperCb.setState(Main.pref.getBoolean("draw.anglesnap.drawConstructionGeometry",true)); 1559 projectionCb.setState(Main.pref.getBoolean("draw.anglesnap.projectionsnapgvff",true)); 1560 add(helperCb); 1561 add(projectionCb);; 1480 1562 add(new AbstractAction(tr("Disable")) { 1481 1563 public void actionPerformed(ActionEvent e) { … … 1486 1568 add(new AbstractAction(tr("0,90,...")) { 1487 1569 public void actionPerformed(ActionEvent e) { 1488 saveAngles("0","90" );1570 saveAngles("0","90","180"); 1489 1571 init(); enableSnapping(); 1490 1572 } … … 1492 1574 add(new AbstractAction(tr("0,45,90,...")) { 1493 1575 public void actionPerformed(ActionEvent e) { 1494 saveAngles("0","45","90","135" );1576 saveAngles("0","45","90","135","180"); 1495 1577 init(); enableSnapping(); 1496 1578 } … … 1498 1580 add(new AbstractAction(tr("0,30,45,60,90,...")) { 1499 1581 public void actionPerformed(ActionEvent e) { 1500 saveAngles("0","30","45","60","90","120","135","150" );1582 saveAngles("0","30","45","60","90","120","135","150","180"); 1501 1583 init(); enableSnapping(); 1502 1584 }
Note:
See TracChangeset
for help on using the changeset viewer.