Introduction
The java en example is extracted from the most popular open source projects, you can refer to the following example for usage.
Programming language: Java
Class/type: EN
Example#1File:
OrthogonalizeAction.javaProject:
ourty196270/josm
/**
* Estimate the direction of the segments, given the first segment points in the direction
* <code>pInitialDirection</code>. Then sum up all horizontal / vertical segments to have a good
* guess for the heading of the entire way.
*
* @param pInitialDirection initial direction
* @throws InvalidUserInputException if selected ways have an angle different from 90 or 180
* degrees
*/
public void calcDirections(Direction pInitialDirection) throws InvalidUserInputException {
final EastNorth[] en =
new EastNorth[nNode]; // alias: way.getNodes().get(i).getEastNorth() ---> en[i]
for (int i = 0; i < nNode; i++) {
en[i] =
new EastNorth(
way.getNodes().get(i).getEastNorth().east(),
way.getNodes().get(i).getEastNorth().north());
}
segDirections = new Direction[nSeg];
Direction direction = pInitialDirection;
segDirections[0] = direction;
for (int i = 0; i < nSeg - 1; i++) {
double h1 = EN.polar(en[i], en[i + 1]);
double h2 = EN.polar(en[i + 1], en[i + 2]);
try {
direction = direction.changeBy(angleToDirectionChange(h2 - h1, TOLERANCE1));
} catch (RejectedAngleException ex) {
throw new InvalidUserInputException(
tr("Please select ways with angles of approximately 90 or 180 degrees."), ex);
}
segDirections[i + 1] = direction;
}
// sum up segments
EastNorth h = new EastNorth(0., 0.);
EastNorth v = new EastNorth(0., 0.);
for (int i = 0; i < nSeg; ++i) {
EastNorth segment = EN.diff(en[i + 1], en[i]);
if (segDirections[i] == Direction.RIGHT) {
h = EN.sum(h, segment);
} else if (segDirections[i] == Direction.UP) {
v = EN.sum(v, segment);
} else if (segDirections[i] == Direction.LEFT) {
h = EN.diff(h, segment);
} else if (segDirections[i] == Direction.DOWN) {
v = EN.diff(v, segment);
} else throw new IllegalStateException();
}
// rotate the vertical vector by 90 degrees (clockwise) and add it to the horizontal vector
segSum = EN.sum(h, new EastNorth(v.north(), -v.east()));
this.heading = EN.polar(new EastNorth(0., 0.), segSum);
}
Example#2File:
OrthogonalizeAction.javaProject:
ourty196270/josm
/**
* Outline: 1. Find direction of all segments - direction = 0..3 (right,up,left,down) - right is
* not really right, you may have to turn your screen 2. Find average heading of all segments -
* heading = angle of a vector in polar coordinates - sum up horizontal segments (those with
* direction 0 or 2) - sum up vertical segments - turn the vertical sum by 90 degrees and add it
* to the horizontal sum - get the average heading from this total sum 3. Rotate all nodes by the
* average heading so that right is really right and all segments are approximately NS or EW. 4.
* If nodes are connected by a horizontal segment: Replace their y-Coordinate by the mean value of
* their y-Coordinates. - The same for vertical segments. 5. Rotate back.
*/
private static Collection<Command> orthogonalize(
List<WayData> wayDataList, List<Node> headingNodes) throws InvalidUserInputException {
// find average heading
double headingAll;
try {
if (headingNodes.isEmpty()) {
// find directions of the segments and make them consistent between different ways
wayDataList.get(0).calcDirections(Direction.RIGHT);
double refHeading = wayDataList.get(0).heading;
EastNorth totSum = new EastNorth(0., 0.);
for (WayData w : wayDataList) {
w.calcDirections(Direction.RIGHT);
int directionOffset = angleToDirectionChange(w.heading - refHeading, TOLERANCE2);
w.calcDirections(Direction.RIGHT.changeBy(directionOffset));
if (angleToDirectionChange(refHeading - w.heading, TOLERANCE2) != 0)
throw new RuntimeException();
totSum = EN.sum(totSum, w.segSum);
}
headingAll = EN.polar(new EastNorth(0., 0.), totSum);
} else {
headingAll =
EN.polar(headingNodes.get(0).getEastNorth(), headingNodes.get(1).getEastNorth());
for (WayData w : wayDataList) {
w.calcDirections(Direction.RIGHT);
int directionOffset = angleToDirectionChange(w.heading - headingAll, TOLERANCE2);
w.calcDirections(Direction.RIGHT.changeBy(directionOffset));
}
}
} catch (RejectedAngleException ex) {
throw new InvalidUserInputException(
tr(
"<html>Please make sure all selected ways head in a similar direction<br>"
+ "or orthogonalize them one by one.</html>"),
ex);
}
// put the nodes of all ways in a set
final Set<Node> allNodes = new HashSet<>();
for (WayData w : wayDataList) {
for (Node n : w.way.getNodes()) {
allNodes.add(n);
}
}
// the new x and y value for each node
final Map<Node, Double> nX = new HashMap<>();
final Map<Node, Double> nY = new HashMap<>();
// calculate the centroid of all nodes
// it is used as rotation center
EastNorth pivot = new EastNorth(0., 0.);
for (Node n : allNodes) {
pivot = EN.sum(pivot, n.getEastNorth());
}
pivot = new EastNorth(pivot.east() / allNodes.size(), pivot.north() / allNodes.size());
// rotate
for (Node n : allNodes) {
EastNorth tmp = EN.rotateCC(pivot, n.getEastNorth(), -headingAll);
nX.put(n, tmp.east());
nY.put(n, tmp.north());
}
// orthogonalize
final Direction[] HORIZONTAL = {Direction.RIGHT, Direction.LEFT};
final Direction[] VERTICAL = {Direction.UP, Direction.DOWN};
final Direction[][] ORIENTATIONS = {HORIZONTAL, VERTICAL};
for (Direction[] orientation : ORIENTATIONS) {
final Set<Node> s = new HashSet<>(allNodes);
int s_size = s.size();
for (int dummy = 0; dummy < s_size; ++dummy) {
if (s.isEmpty()) {
break;
}
final Node dummy_n = s.iterator().next(); // pick arbitrary element of s
final Set<Node> cs =
new HashSet<>(); // will contain each node that can be reached from dummy_n
cs.add(dummy_n); // walking only on horizontal / vertical segments
boolean somethingHappened = true;
while (somethingHappened) {
somethingHappened = false;
for (WayData w : wayDataList) {
for (int i = 0; i < w.nSeg; ++i) {
Node n1 = w.way.getNodes().get(i);
Node n2 = w.way.getNodes().get(i + 1);
if (Arrays.asList(orientation).contains(w.segDirections[i])) {
if (cs.contains(n1) && !cs.contains(n2)) {
cs.add(n2);
somethingHappened = true;
}
if (cs.contains(n2) && !cs.contains(n1)) {
cs.add(n1);
somethingHappened = true;
}
}
}
}
}
final Map<Node, Double> nC = (orientation == HORIZONTAL) ? nY : nX;
double average = 0;
for (Node n : cs) {
s.remove(n);
average += nC.get(n).doubleValue();
}
average = average / cs.size();
// if one of the nodes is a heading node, forget about the average and use its value
for (Node fn : headingNodes) {
if (cs.contains(fn)) {
average = nC.get(fn);
}
}
// At this point, the two heading nodes (if any) are horizontally aligned, i.e. they
// have the same y coordinate. So in general we shouldn't find them in a vertical string
// of segments. This can still happen in some pathological cases (see #7889). To avoid
// both heading nodes collapsing to one point, we simply skip this segment string and
// don't touch the node coordinates.
if (orientation == VERTICAL && headingNodes.size() == 2 && cs.containsAll(headingNodes)) {
continue;
}
for (Node n : cs) {
nC.put(n, average);
}
}
if (!s.isEmpty()) throw new RuntimeException();
}
// rotate back and log the change
final Collection<Command> commands = new LinkedList<>();
for (Node n : allNodes) {
EastNorth tmp = new EastNorth(nX.get(n), nY.get(n));
tmp = EN.rotateCC(pivot, tmp, headingAll);
final double dx = tmp.east() - n.getEastNorth().east();
final double dy = tmp.north() - n.getEastNorth().north();
if (headingNodes.contains(n)) { // The heading nodes should not have changed
final double EPSILON = 1E-6;
if (Math.abs(dx) > Math.abs(EPSILON * tmp.east())
|| Math.abs(dy) > Math.abs(EPSILON * tmp.east())) throw new AssertionError();
} else {
OrthogonalizeAction.rememberMovements.put(n, new EastNorth(dx, dy));
commands.add(new MoveCommand(n, dx, dy));
}
}
return commands;
}