use of org.openstreetmap.josm.data.osm.Node in project josm by JOSM.
the class AddNodeAction method actionPerformed.
@Override
public void actionPerformed(ActionEvent e) {
if (!isEnabled())
return;
// #17682 - Run the action later in EDT to make sure the KeyEvent triggering it is consumed before the dialog is shown
SwingUtilities.invokeLater(() -> {
LatLonDialog dialog = new LatLonDialog(MainApplication.getMainFrame(), tr("Add Node..."), ht("/Action/AddNode"));
if (textLatLon != null) {
dialog.setLatLonText(textLatLon);
}
if (textEastNorth != null) {
dialog.setEastNorthText(textEastNorth);
}
dialog.showDialog();
if (dialog.getValue() != 1)
return;
LatLon coordinates = dialog.getCoordinates();
if (coordinates == null)
return;
textLatLon = dialog.getLatLonText();
textEastNorth = dialog.getEastNorthText();
Node nnew = new Node(coordinates);
// add the node
DataSet ds = getLayerManager().getEditDataSet();
UndoRedoHandler.getInstance().add(new AddCommand(ds, nnew));
ds.setSelected(nnew);
MapView mapView = MainApplication.getMap().mapView;
if (mapView != null && !mapView.getRealBounds().contains(nnew.getCoor())) {
AutoScaleAction.zoomTo(Collections.<OsmPrimitive>singleton(nnew));
}
});
}
use of org.openstreetmap.josm.data.osm.Node in project josm by JOSM.
the class AlignInLineAction method getInvolvedLines.
/**
* Get lines useful to do alignment of a single node
* @param node Node to be aligned
* @param refWays Ways where useful lines will be searched
* @return List of useful lines
* @throws InvalidSelection if a node got more than 4 neighbours (self-crossing way)
*/
private static List<Line> getInvolvedLines(Node node, List<Way> refWays) throws InvalidSelection {
List<Line> lines = new ArrayList<>();
List<Node> neighbors = new ArrayList<>();
for (Way way : refWays) {
List<Node> nodes = way.getNodes();
neighbors.clear();
for (int i = 1; i < nodes.size() - 1; i++) {
if (nodes.get(i) == node) {
neighbors.add(nodes.get(i - 1));
neighbors.add(nodes.get(i + 1));
}
}
if (neighbors.isEmpty())
continue;
else if (neighbors.size() == 2)
// Non self crossing
lines.add(new Line(neighbors.get(0), neighbors.get(1)));
else if (neighbors.size() == 4) {
// Self crossing, have to make 2 lines with 4 neighbors
// see #9081 comment 6
EastNorth c = node.getEastNorth();
double[] angle = IntStream.range(0, 4).mapToDouble(i -> PolarCoor.computeAngle(neighbors.get(i).getEastNorth(), c)).toArray();
double[] deltaAngle = new double[3];
for (int i = 0; i < 3; i++) {
deltaAngle[i] = angle[i + 1] - angle[0];
if (deltaAngle[i] < 0)
deltaAngle[i] += 2 * Math.PI;
}
int nb = 0;
if (deltaAngle[1] < deltaAngle[0])
nb++;
if (deltaAngle[2] < deltaAngle[0])
nb++;
if (nb == 1) {
// Align along [neighbors[0], neighbors[1]] and [neighbors[0], neighbors[2]]
lines.add(new Line(neighbors.get(0), neighbors.get(1)));
lines.add(new Line(neighbors.get(2), neighbors.get(3)));
} else {
// Align along [neighbors[0], neighbors[2]] and [neighbors[1], neighbors[3]]
lines.add(new Line(neighbors.get(0), neighbors.get(2)));
lines.add(new Line(neighbors.get(1), neighbors.get(3)));
}
} else
throw new InvalidSelection("cannot treat more than 4 neighbours, got " + neighbors.size());
}
return lines;
}
use of org.openstreetmap.josm.data.osm.Node in project josm by JOSM.
the class AlignInLineAction method alignMultiWay.
/**
* Align way in case of multiple way #6819
* @param ways Collection of way to align
* @return Command that perform action
* @throws InvalidSelection if a polygon is selected, or if a node is used by 3 or more ways
*/
private static Command alignMultiWay(Collection<Way> ways) throws InvalidSelection {
// Collect all nodes and compute line equation
Set<Node> nodes = new HashSet<>();
Map<Way, Line> lines = new HashMap<>();
for (Way w : ways) {
if (w.isClosed())
throw new InvalidSelection(tr("Can not align a polygon. Abort."));
if (!w.isEmpty()) {
nodes.addAll(w.getNodes());
lines.put(w, new Line(w));
}
}
if (nodes.isEmpty()) {
throw new InvalidSelection(tr("Intersection of three or more ways can not be solved. Abort."));
}
Collection<Command> cmds = new ArrayList<>(nodes.size());
List<Way> referrers = new ArrayList<>(ways.size());
for (Node n : nodes) {
referrers.clear();
for (OsmPrimitive o : n.getReferrers()) {
if (ways.contains(o))
referrers.add((Way) o);
}
if (referrers.size() == 1) {
Way way = referrers.get(0);
if (way.isFirstLastNode(n))
continue;
cmds.add(lines.get(way).projectionCommand(n));
} else if (referrers.size() == 2) {
cmds.add(lines.get(referrers.get(0)).intersectionCommand(n, lines.get(referrers.get(1))));
} else
throw new InvalidSelection(tr("Intersection of three or more ways can not be solved. Abort."));
}
return cmds.isEmpty() ? null : new SequenceCommand(tr("Align Nodes in Line"), cmds);
}
use of org.openstreetmap.josm.data.osm.Node in project josm by JOSM.
the class CombineWayAction method actionPerformed.
@Override
public void actionPerformed(ActionEvent event) {
final DataSet ds = getLayerManager().getEditDataSet();
if (ds == null)
return;
Collection<Way> selectedWays = new LinkedHashSet<>(ds.getSelectedWays());
selectedWays.removeIf(Way::isEmpty);
if (selectedWays.size() < 2) {
new Notification(tr("Please select at least two ways to combine.")).setIcon(JOptionPane.INFORMATION_MESSAGE).setDuration(Notification.TIME_SHORT).show();
return;
}
// see #18083: check if we will combine ways at nodes outside of the download area
Set<Node> endNodesOutside = new HashSet<>();
for (Way w : selectedWays) {
final Node[] endnodes = { w.firstNode(), w.lastNode() };
for (Node n : endnodes) {
if (!n.isNew() && n.isOutsideDownloadArea() && !endNodesOutside.add(n)) {
new Notification(tr("Combine ways refused<br>" + "(A shared node is outside of the download area)")).setIcon(JOptionPane.INFORMATION_MESSAGE).show();
return;
}
}
}
// combine and update gui
Pair<Way, Command> combineResult;
try {
combineResult = combineWaysWorker(selectedWays);
} catch (UserCancelException ex) {
Logging.trace(ex);
return;
}
if (combineResult == null)
return;
final Way selectedWay = combineResult.a;
UndoRedoHandler.getInstance().add(combineResult.b);
Test test = new OverlappingWays();
test.startTest(null);
test.visit(combineResult.a);
test.endTest();
if (test.getErrors().isEmpty()) {
test = new SelfIntersectingWay();
test.startTest(null);
test.visit(combineResult.a);
test.endTest();
}
if (!test.getErrors().isEmpty()) {
new Notification(test.getErrors().get(0).getMessage()).setIcon(JOptionPane.WARNING_MESSAGE).setDuration(Notification.TIME_SHORT).show();
}
if (selectedWay != null) {
GuiHelper.runInEDT(() -> ds.setSelected(selectedWay));
}
}
use of org.openstreetmap.josm.data.osm.Node in project josm by JOSM.
the class SplitWayCommand method buildSplitChunks.
/**
* Splits the nodes of {@code wayToSplit} into a list of node sequences
* which are separated at the nodes in {@code splitPoints}.
*
* This method displays warning messages if {@code wayToSplit} and/or
* {@code splitPoints} aren't consistent.
*
* Returns null, if building the split chunks fails.
*
* @param wayToSplit the way to split. Must not be null.
* @param splitPoints the nodes where the way is split. Must not be null.
* @return the list of chunks
*/
public static List<List<Node>> buildSplitChunks(Way wayToSplit, List<Node> splitPoints) {
CheckParameterUtil.ensureParameterNotNull(wayToSplit, "wayToSplit");
CheckParameterUtil.ensureParameterNotNull(splitPoints, "splitPoints");
Set<Node> nodeSet = new HashSet<>(splitPoints);
List<List<Node>> wayChunks = new LinkedList<>();
List<Node> currentWayChunk = new ArrayList<>();
wayChunks.add(currentWayChunk);
Iterator<Node> it = wayToSplit.getNodes().iterator();
while (it.hasNext()) {
Node currentNode = it.next();
boolean atEndOfWay = currentWayChunk.isEmpty() || !it.hasNext();
currentWayChunk.add(currentNode);
if (nodeSet.contains(currentNode) && !atEndOfWay) {
currentWayChunk = new ArrayList<>();
currentWayChunk.add(currentNode);
wayChunks.add(currentWayChunk);
}
}
// Handle circular ways specially.
// If you split at a circular way at two nodes, you just want to split
// it at these points, not also at the former endpoint.
// So if the last node is the same first node, join the last and the
// first way chunk.
List<Node> lastWayChunk = wayChunks.get(wayChunks.size() - 1);
if (wayChunks.size() >= 2 && wayChunks.get(0).get(0) == lastWayChunk.get(lastWayChunk.size() - 1) && !nodeSet.contains(wayChunks.get(0).get(0))) {
if (wayChunks.size() == 2) {
warningNotifier.accept(tr("You must select two or more nodes to split a circular way."));
return null;
}
lastWayChunk.remove(lastWayChunk.size() - 1);
lastWayChunk.addAll(wayChunks.get(0));
wayChunks.remove(wayChunks.size() - 1);
wayChunks.set(0, lastWayChunk);
}
if (wayChunks.size() < 2) {
if (wayChunks.get(0).get(0) == wayChunks.get(0).get(wayChunks.get(0).size() - 1)) {
warningNotifier.accept(tr("You must select two or more nodes to split a circular way."));
} else {
warningNotifier.accept(tr("The way cannot be split at the selected nodes. (Hint: Select nodes in the middle of the way.)"));
}
return null;
}
return wayChunks;
}
Aggregations