4141 * <li>{@link DecreasingShapeDistanceNotice}
4242 * <li>{@link EqualShapeDistanceSameCoordinatesNotice}
4343 * <li>{@link EqualShapeDistanceDiffCoordinatesNotice}
44+ * <li>{@link EqualShapeDistanceDiffCoordinatesWarningNotice}
4445 * </ul>
4546 */
4647@ GtfsValidator
4748public class ShapeIncreasingDistanceValidator extends FileValidator {
4849
4950 private final GtfsShapeTableContainer table ;
51+ private final double DISTANCE_THRESHOLD = 1.11 ;
5052
5153 @ Inject
5254 ShapeIncreasingDistanceValidator (GtfsShapeTableContainer table ) {
@@ -72,8 +74,15 @@ public void validate(NoticeContainer noticeContainer) {
7274 }
7375 // equal shape_dist_traveled and different coordinates
7476 if (!(curr .shapePtLon () == prev .shapePtLon () && curr .shapePtLat () == prev .shapePtLat ())) {
75- noticeContainer .addValidationNotice (
76- new EqualShapeDistanceDiffCoordinatesNotice (prev , curr ));
77+ double distanceBetweenShapePoints =
78+ getDistanceMeters (curr .shapePtLatLon (), prev .shapePtLatLon ());
79+ if (distanceBetweenShapePoints >= DISTANCE_THRESHOLD ) {
80+ noticeContainer .addValidationNotice (
81+ new EqualShapeDistanceDiffCoordinatesNotice (prev , curr ));
82+ } else if (distanceBetweenShapePoints > 0 ) {
83+ noticeContainer .addValidationNotice (
84+ new EqualShapeDistanceDiffCoordinatesWarningNotice (prev , curr ));
85+ }
7786 } else {
7887 // equal shape_dist_traveled and same coordinates
7988 noticeContainer .addValidationNotice (
@@ -177,7 +186,7 @@ static class EqualShapeDistanceSameCoordinatesNotice extends ValidationNotice {
177186
178187 /**
179188 * Two consecutive points have equal `shape_dist_traveled` and different lat/lon coordinates in
180- * `shapes.txt`.
189+ * `shapes.txt` and the distance between the two points is greater than the 1.11m .
181190 *
182191 * <p>When sorted by `shape.shape_pt_sequence`, the values for `shape_dist_traveled` must increase
183192 * along a shape. Two consecutive points with equal values for `shape_dist_traveled` and different
@@ -225,4 +234,56 @@ static class EqualShapeDistanceDiffCoordinatesNotice extends ValidationNotice {
225234 getDistanceMeters (current .shapePtLatLon (), previous .shapePtLatLon ());
226235 }
227236 }
237+
238+ /**
239+ * Two consecutive points have equal `shape_dist_traveled` and different lat/lon coordinates in
240+ * `shapes.txt` and the distance between the two points is less than 1.11m.
241+ *
242+ * <p>When sorted by `shape.shape_pt_sequence`, the values for `shape_dist_traveled` must increase
243+ * along a shape. Two consecutive points with equal values for `shape_dist_traveled` and different
244+ * coordinates indicate an error.
245+ */
246+ @ GtfsValidationNotice (
247+ severity = WARNING ,
248+ files = @ FileRefs ({GtfsShapeSchema .class , GtfsStopSchema .class }))
249+ static class EqualShapeDistanceDiffCoordinatesWarningNotice extends ValidationNotice {
250+
251+ /** The id of the faulty shape. */
252+ private final String shapeId ;
253+
254+ /** The row number from `shapes.txt`. */
255+ private final int csvRowNumber ;
256+
257+ /** The faulty record's `shape_dist_traveled` value. */
258+ private final double shapeDistTraveled ;
259+
260+ /** The faulty record's `shapes.shape_pt_sequence`. */
261+ private final int shapePtSequence ;
262+
263+ /** The row number from `shapes.txt` of the previous shape point. */
264+ private final long prevCsvRowNumber ;
265+
266+ /** The previous shape point's `shape_dist_traveled` value. */
267+ private final double prevShapeDistTraveled ;
268+
269+ /** The previous record's `shapes.shape_pt_sequence`. */
270+ private final int prevShapePtSequence ;
271+
272+ /**
273+ * Actual distance traveled along the shape from the first shape point to the previous shape.
274+ */
275+ private final double actualDistanceBetweenShapePoints ;
276+
277+ EqualShapeDistanceDiffCoordinatesWarningNotice (GtfsShape previous , GtfsShape current ) {
278+ this .shapeId = current .shapeId ();
279+ this .csvRowNumber = current .csvRowNumber ();
280+ this .shapeDistTraveled = current .shapeDistTraveled ();
281+ this .shapePtSequence = current .shapePtSequence ();
282+ this .prevCsvRowNumber = previous .csvRowNumber ();
283+ this .prevShapeDistTraveled = previous .shapeDistTraveled ();
284+ this .prevShapePtSequence = previous .shapePtSequence ();
285+ this .actualDistanceBetweenShapePoints =
286+ getDistanceMeters (current .shapePtLatLon (), previous .shapePtLatLon ());
287+ }
288+ }
228289}
0 commit comments