4141 * <li>{@link DecreasingShapeDistanceNotice}
4242 * <li>{@link EqualShapeDistanceSameCoordinatesNotice}
4343 * <li>{@link EqualShapeDistanceDiffCoordinatesNotice}
44+ * <li>{@link EqualShapeDistanceDiffCoordinatesDistanceBelowThresholdNotice}
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 EqualShapeDistanceDiffCoordinatesDistanceBelowThresholdNotice (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
@@ -209,8 +218,10 @@ static class EqualShapeDistanceDiffCoordinatesNotice extends ValidationNotice {
209218 /** The previous record's `shapes.shape_pt_sequence`. */
210219 private final int prevShapePtSequence ;
211220
212- // Actual distance traveled along the shape from the first shape point to the previous shape
213- /** point. */
221+ /**
222+ * Actual distance traveled along the shape from the first shape point to the previous shape
223+ * point.
224+ */
214225 private final double actualDistanceBetweenShapePoints ;
215226
216227 EqualShapeDistanceDiffCoordinatesNotice (GtfsShape previous , GtfsShape current ) {
@@ -225,4 +236,59 @@ static class EqualShapeDistanceDiffCoordinatesNotice extends ValidationNotice {
225236 getDistanceMeters (current .shapePtLatLon (), previous .shapePtLatLon ());
226237 }
227238 }
239+
240+ /**
241+ * Two consecutive points have equal `shape_dist_traveled` and different lat/lon coordinates in
242+ * `shapes.txt` and the distance between the two points is less than 1.11m.
243+ *
244+ * <p>When sorted by `shape.shape_pt_sequence`, the values for `shape_dist_traveled` must increase
245+ * along a shape. Two consecutive points with equal values for `shape_dist_traveled` and different
246+ * coordinates indicate an error.
247+ */
248+ @ GtfsValidationNotice (
249+ severity = WARNING ,
250+ files = @ FileRefs ({GtfsShapeSchema .class , GtfsStopSchema .class }))
251+ static class EqualShapeDistanceDiffCoordinatesDistanceBelowThresholdNotice
252+ extends ValidationNotice {
253+
254+ /** The id of the faulty shape. */
255+ private final String shapeId ;
256+
257+ /** The row number from `shapes.txt`. */
258+ private final int csvRowNumber ;
259+
260+ /** The faulty record's `shape_dist_traveled` value. */
261+ private final double shapeDistTraveled ;
262+
263+ /** The faulty record's `shapes.shape_pt_sequence`. */
264+ private final int shapePtSequence ;
265+
266+ /** The row number from `shapes.txt` of the previous shape point. */
267+ private final long prevCsvRowNumber ;
268+
269+ /** The previous shape point's `shape_dist_traveled` value. */
270+ private final double prevShapeDistTraveled ;
271+
272+ /** The previous record's `shapes.shape_pt_sequence`. */
273+ private final int prevShapePtSequence ;
274+
275+ /**
276+ * Actual distance traveled along the shape from the first shape point to the previous shape
277+ * point.
278+ */
279+ private final double actualDistanceBetweenShapePoints ;
280+
281+ EqualShapeDistanceDiffCoordinatesDistanceBelowThresholdNotice (
282+ GtfsShape previous , GtfsShape current ) {
283+ this .shapeId = current .shapeId ();
284+ this .csvRowNumber = current .csvRowNumber ();
285+ this .shapeDistTraveled = current .shapeDistTraveled ();
286+ this .shapePtSequence = current .shapePtSequence ();
287+ this .prevCsvRowNumber = previous .csvRowNumber ();
288+ this .prevShapeDistTraveled = previous .shapeDistTraveled ();
289+ this .prevShapePtSequence = previous .shapePtSequence ();
290+ this .actualDistanceBetweenShapePoints =
291+ getDistanceMeters (current .shapePtLatLon (), previous .shapePtLatLon ());
292+ }
293+ }
228294}
0 commit comments