/** Add a ring to a builder */ private void addRing(LineString r, Geobuf.Data.Geometry.Builder builder) { // skip last point, same as first builder.addLengths(r.getNumPoints() - 1); long x, y, prevX = 0, prevY = 0; // last point is same as first, skip for (int i = 0; i < r.getNumPoints() - 1; i++) { // delta code Coordinate coord = r.getCoordinateN(i); // note that roundoff errors do not accumulate x = (long) (coord.x * precisionMultiplier); y = (long) (coord.y * precisionMultiplier); builder.addCoords(x - prevX); builder.addCoords(y - prevY); prevX = x; prevY = y; } }
/** Moves the iterator ahead to the next vertex and (possibly) linear component. */ public void next() { if (!hasNext()) return; vertexIndex++; if (vertexIndex >= currentLine.getNumPoints()) { componentIndex++; loadCurrentLine(); vertexIndex = 0; } }
/** calculate the length of this street segement from its geometry */ protected void calculateLengthFromGeometry() { double accumulatedMeters = 0; LineString geom = getGeometry(); for (int i = 1; i < geom.getNumPoints(); i++) { accumulatedMeters += SphericalDistanceLibrary.distance(geom.getCoordinateN(i - 1), geom.getCoordinateN(i)); } length_mm = (int) (accumulatedMeters * 1000); }
private boolean testForUshape( Edge edge, long maxTime, long fromTime, long toTime, double angleLimit, double distanceTolerance, double userSpeed, boolean hasCar, boolean performSpeedTest) { LineString ls = (LineString) edge.getGeometry(); if (ls.getNumPoints() <= 3) { // first filter since u-shapes need at least 4 pts // this is the normal case return false; } else { // try to identify u-shapes by checking if the angle EndPoint-StartPoint-StartPoint+1 // is about 90 degrees (using Azimuths on the sphere) double diffTo90Azimuths = 360; if (edge instanceof PlainStreetEdge) { double firstSegmentAngle = DirectionUtils.getFirstAngle(edge.getGeometry()); if (firstSegmentAngle < 0) firstSegmentAngle = firstSegmentAngle + Math.PI; double firstToLastSegmentAngle = getFirstToLastSegmentAngle(edge.getGeometry()); if (firstToLastSegmentAngle < 0) firstToLastSegmentAngle = firstToLastSegmentAngle + Math.PI; double diffAzimuths = Math.abs(firstToLastSegmentAngle - firstSegmentAngle); diffTo90Azimuths = Math.abs(diffAzimuths - (Math.PI / 2.0)); } else { // this will happen in particular for transit routes // LOG.debug("Edge is not a PlainStreetEdge"); } if (diffTo90Azimuths < angleLimit) { // no need to test further if we know its a u-shape // System.out.println("u-shape found, (spherical) angle: " + diffTo90Azimuths* 180/Math.PI); return true; } else { if (performSpeedTest) { // Use also a distance based criteria since the angle criteria may fail. // However a distance based one may fail as well for steep terrain. long dt = Math.abs(toTime - fromTime); double lineDist = edge.getDistance(); double distanceToWalkInTimeMissing = distanceToMoveInRemainingTime(maxTime, fromTime, dt, userSpeed, edge, hasCar, false); double approxWalkableDistanceInTime = distanceToWalkInTimeMissing * distanceTolerance; if ((approxWalkableDistanceInTime < lineDist)) { return true; } } return false; } } }
/** * Make sure the network doesn't have any problems * * @param n - the network to be tested */ static void testNetworkForIssues(Network n) { System.out.println("testing"); for (Object o : n.allNodes) { GeoNode node = (GeoNode) o; for (Object p : n.getEdgesOut(node)) { sim.field.network.Edge e = (sim.field.network.Edge) p; LineString ls = (LineString) ((MasonGeometry) e.info).geometry; Coordinate c1 = ls.getCoordinateN(0); Coordinate c2 = ls.getCoordinateN(ls.getNumPoints() - 1); GeoNode g1 = (GeoNode) e.getFrom(); GeoNode g2 = (GeoNode) e.getTo(); if (c1.distance(g1.geometry.getCoordinate()) > 1) System.out.println("found you"); if (c2.distance(g2.geometry.getCoordinate()) > 1) System.out.println("found you"); } } }
/** * Computes the angle from the first point to the last point of a LineString or MultiLineString. * TODO: put this method into org.opentripplanner.common.geometry.DirectionUtils * * @param geometry a LineString or a MultiLineString * @return */ public synchronized double getFirstToLastSegmentAngle(Geometry geometry) { LineString line; if (geometry instanceof MultiLineString) { line = (LineString) geometry.getGeometryN(geometry.getNumGeometries() - 1); } else { assert geometry instanceof LineString; line = (LineString) geometry; } int numPoints = line.getNumPoints(); Coordinate coord0 = line.getCoordinateN(0); Coordinate coord1 = line.getCoordinateN(numPoints - 1); int i = numPoints - 3; while (distanceLibrary.fastDistance(coord0, coord1) < 10 && i >= 0) { coord1 = line.getCoordinateN(i--); } geodeticCalculator.setStartingGeographicPoint(coord0.x, coord0.y); geodeticCalculator.setDestinationGeographicPoint(coord1.x, coord1.y); return geodeticCalculator.getAzimuth() * Math.PI / 180; }
private void writeLineString(LineString geom, ValueSetter dest) { dest.setInt(geom.getNumPoints()); writeCoordinates(geom.getCoordinateSequence(), getCoordDim(geom), dest); }
boolean layout(LineLabel label, LabelIndex labels) { String txt = label.getText(); Rule rule = label.getRule(); Feature f = label.getFeature(); Geometry g = label.getGeometry(); LineString line = null; if (g instanceof MultiLineString) { // TODO: handle multiple lines if (g.getNumGeometries() == 1) { line = (LineString) g.getGeometryN(0); } } else { line = (LineString) g; } if (line == null) { return false; } Paint p = label.get(Paint.class, Paint.class); // compute the bounds of the label with no rotation Rect r = new Rect(); p.getTextBounds(txt, 0, txt.length(), r); // map it to world coordinates RectF bounds = new RectF(r); tx.getCanvasToWorld().mapRect(bounds); // ignore label if its too long for the line if (line.getLength() < bounds.width()) { // ignore this label return false; } // reverse if (line.getPointN(0).getX() > line.getPointN(line.getNumPoints() - 1).getX()) { line = (LineString) line.reverse(); } // compute width of individual letters float[] widths = new float[txt.length()]; p.getTextWidths(txt, widths); // map the widths to world space float sum = 0; for (int i = 0; i < widths.length; i++) { RectF s = new RectF(0, 0, widths[i], 1); tx.getCanvasToWorld().mapRect(s); widths[i] = s.width(); sum += s.width(); } // TODO: properly figure out spacing between letters float space = tx.getCanvasToWorld().mapRadius(1); // allowable angle change in consecutive characters double maxAngleDelta = rule.number(f, TEXT_MAX_CHAR_ANGLE_DELTA, DEFAULT_MAX_ANGLE_CHAR_DELTA); // // sample points along the line for letters // List<LineSegment> path = new ArrayList<LineSegment>(); LineSampler sampler = new LineSampler(line.getCoordinates()); for (int i = 0; i < txt.length(); i++) { // get next point Coordinate c1 = sampler.sample(); // advance by width of letter sampler.advance(widths[i]); // get point for end of letter Coordinate c2 = sampler.sample(); if (c1 == null || c2 == null) { // ran out of room return false; } LineSegment seg = new LineSegment(c1, c2); // check angle made with previous segment if (i > 0) { LineSegment prev = path.get(i - 1); if (Math.abs(angle(seg) - angle(prev)) > maxAngleDelta) { return false; } } path.add(seg); sampler.advance(space); } label.setPath(path); label.setShape(toShape(path, bounds.height())); return labels.insert(label); }
/** * Tests whether there are any vertices left to iterator over. Specifically, hasNext() return * <tt>true</tt> if the current state of the iterator represents a valid location on the linear * geometry. * * @return <code>true</code> if there are more vertices to scan */ public boolean hasNext() { if (componentIndex >= numLines) return false; if (componentIndex == numLines - 1 && vertexIndex >= currentLine.getNumPoints()) return false; return true; }
/** * Checks whether the iterator cursor is pointing to the * endpoint of a component {@link LineString}. * * @return <code>true</true> if the iterator is at an endpoint */ public boolean isEndOfLine() { if (componentIndex >= numLines) return false; // LineString currentLine = (LineString) linear.getGeometryN(componentIndex); if (vertexIndex < currentLine.getNumPoints() - 1) return false; return true; }