Returns true if polyline_a touches multipoint_b.
322657
private static boolean polylineTouchesMultiPoint_(Polyline polyline_a,
			MultiPoint multipoint_b, double tolerance,
			ProgressTracker progress_tracker) {
		// Quick rasterize test to see whether the the geometries are disjoint.
		if (tryRasterizedContainsOrDisjoint_(polyline_a, multipoint_b,
				tolerance, false) == Relation.disjoint) {
			return false;
		}

		SegmentIteratorImpl segIterA = ((MultiPathImpl) polyline_a._getImpl())
				.querySegmentIterator();

		Envelope2D env_a = new Envelope2D();
		Envelope2D env_b = new Envelope2D();
		Envelope2D envInter = new Envelope2D();
		polyline_a.queryEnvelope2D(env_a);
		multipoint_b.queryEnvelope2D(env_b);
		env_a.inflate(tolerance, tolerance);
		env_b.inflate(tolerance, tolerance);
		envInter.setCoords(env_a);
		envInter.intersect(env_b);

		QuadTreeImpl qtA = null;
		QuadTreeImpl quadTreeA = null;
        QuadTreeImpl quadTreePathsA = null;

		GeometryAccelerators accel = ((MultiPathImpl) (polyline_a._getImpl()))
				._getAccelerators();

		if (accel != null) {
			quadTreeA = accel.getQuadTree();
            quadTreePathsA = accel.getQuadTreeForPaths();
			if (quadTreeA == null) {
				qtA = InternalUtils.buildQuadTree(
						(MultiPathImpl) polyline_a._getImpl(), envInter);
				quadTreeA = qtA;
			}
		} else {
			qtA = InternalUtils.buildQuadTree(
					(MultiPathImpl) polyline_a._getImpl(), envInter);
			quadTreeA = qtA;
		}

		QuadTreeImpl.QuadTreeIteratorImpl qtIterA = quadTreeA.getIterator();

        QuadTreeImpl.QuadTreeIteratorImpl qtIterPathsA = null;
        if (quadTreePathsA != null)
            qtIterPathsA = quadTreePathsA.getIterator();

		Point2D ptB = new Point2D(), closest = new Point2D();
		boolean b_intersects = false;
		double toleranceSq = tolerance * tolerance;

		AttributeStreamOfInt8 intersects = new AttributeStreamOfInt8(
				multipoint_b.getPointCount());
		for (int i = 0; i < multipoint_b.getPointCount(); i++) {
			intersects.write(i, (byte) 0);
		}

		for (int i = 0; i < multipoint_b.getPointCount(); i++) {
			multipoint_b.getXY(i, ptB);

			if (!envInter.contains(ptB)) {
				continue;
			}

			env_b.setCoords(ptB.x, ptB.y, ptB.x, ptB.y);

            if (qtIterPathsA != null) {
                qtIterPathsA.resetIterator(env_b, tolerance);

                if (qtIterPathsA.next() == -1)
                    continue;
            }

			qtIterA.resetIterator(env_b, tolerance);

			for (int elementHandleA = qtIterA.next(); elementHandleA != -1; elementHandleA = qtIterA
					.next()) {
				int vertex_a = quadTreeA.getElement(elementHandleA);
				segIterA.resetToVertex(vertex_a);

				Segment segmentA = segIterA.nextSegment();
				double t = segmentA.getClosestCoordinate(ptB, false);
				segmentA.getCoord2D(t, closest);

				if (Point2D.sqrDistance(ptB, closest) <= toleranceSq) {
					intersects.write(i, (byte) 1);
					b_intersects = true;
					break;
				}
			}
		}

		if (!b_intersects) {
			return false;
		}

		MultiPoint boundary_a = (MultiPoint) (polyline_a.getBoundary());
		MultiPoint multipoint_b_inter = new MultiPoint();
		Point2D pt = new Point2D();

		for (int i = 0; i < multipoint_b.getPointCount(); i++) {
			if (intersects.read(i) == 0) {
				continue;
			}

			multipoint_b.getXY(i, pt);
			multipoint_b_inter.add(pt.x, pt.y);
		}

		return multiPointContainsMultiPointBrute_(boundary_a,
				multipoint_b_inter, tolerance);
	}
614221
private static boolean multiPointContainsMultiPoint_(
			MultiPoint multipoint_a, MultiPoint multipoint_b, double tolerance,
			ProgressTracker progress_tracker) {
		Envelope2D env_a = new Envelope2D(), env_b = new Envelope2D();
		multipoint_a.queryEnvelope2D(env_a);
		multipoint_b.queryEnvelope2D(env_b);

		if (!envelopeInfContainsEnvelope_(env_a, env_b, tolerance))
			return false;

		return multiPointCoverageMultiPoint_(multipoint_b, multipoint_a,
				tolerance, true, false, false, progress_tracker);
	}
392585
static boolean pointRelatePoint_(Point point_a, Point point_b,
			double tolerance, String scl, ProgressTracker progress_tracker) {
		Point2D pt_a = point_a.getXY();
		Point2D pt_b = point_b.getXY();
		int[] matrix = new int[9];

		for (int i = 0; i < 9; i++)
			matrix[i] = -1;

		if (Point2D.sqrDistance(pt_a, pt_b) <= tolerance * tolerance) {
			matrix[MatrixPredicate.InteriorInterior] = 0;
		} else {
			matrix[MatrixPredicate.InteriorExterior] = 0;
			matrix[MatrixPredicate.ExteriorInterior] = 0;
		}

		matrix[MatrixPredicate.ExteriorExterior] = 2;

		boolean bRelation = relationCompare_(matrix, scl);
		return bRelation;
	}
1096843
private static boolean polygonContainsMultiPoint_(Polygon polygon_a,
			MultiPoint multipoint_b, double tolerance,
			ProgressTracker progress_tracker) {
		Envelope2D env_a = new Envelope2D(), env_b = new Envelope2D();
		polygon_a.queryEnvelope2D(env_a);
		multipoint_b.queryEnvelope2D(env_b);

		// Quick envelope rejection test for false equality.
		if (!envelopeInfContainsEnvelope_(env_a, env_b, tolerance))
			return false;

		// Quick rasterize test to see whether the the geometries are disjoint,
		// or if one is contained in the other.
		int relation = tryRasterizedContainsOrDisjoint_(polygon_a,
				multipoint_b, tolerance, false);

		if (relation == Relation.disjoint)
			return false;

		if (relation == Relation.contains)
			return true;

        boolean b_interior = false;
        Point2D ptB;

        MultiPathImpl polygon_a_impl = (MultiPathImpl)polygon_a._getImpl();

        Polygon pa = null;
        Polygon p_polygon_a = polygon_a;

        boolean b_checked_polygon_a_quad_tree = false;

        for (int i = 0; i < multipoint_b.getPointCount(); i++)
        {
            ptB = multipoint_b.getXY(i);

            if (!env_a.contains(ptB))
                return false;

            PolygonUtils.PiPResult result = PolygonUtils.isPointInPolygon2D(p_polygon_a, ptB, tolerance);

            if (result == PolygonUtils.PiPResult.PiPInside)
                b_interior = true;
            else if (result == PolygonUtils.PiPResult.PiPOutside)
                return false;

            if (!b_checked_polygon_a_quad_tree) {
                if (PointInPolygonHelper.quadTreeWillHelp(polygon_a, multipoint_b.getPointCount() - 1) && (polygon_a_impl._getAccelerators() == null || polygon_a_impl._getAccelerators().getQuadTree() == null)) {
                    pa = new Polygon();
                    polygon_a.copyTo(pa);
                    ((MultiPathImpl) pa._getImpl())._buildQuadTreeAccelerator(Geometry.GeometryAccelerationDegree.enumMedium);
                    p_polygon_a = pa;
                } else {
                    p_polygon_a = polygon_a;
                }

                b_checked_polygon_a_quad_tree = true;
            }
        }

        return b_interior;
	}
762066
private static boolean multiPointWithinPoint_(MultiPoint multipoint_a,
			Point point_b, double tolerance, ProgressTracker progress_tracker) {
		return multiPointEqualsPoint_(multipoint_a, point_b, tolerance,
				progress_tracker);
	}
389435
private static boolean multiPointDisjointPoint_(MultiPoint multipoint_a,
			Point point_b, double tolerance, ProgressTracker progress_tracker) {
		Point2D pt_b = point_b.getXY();
		return multiPointDisjointPointImpl_(multipoint_a, pt_b, tolerance,
				progress_tracker);
	}
1289874
private static boolean polylineOverlapsEnvelope_(Polyline polyline_a,
			Envelope envelope_b, double tolerance,
			ProgressTracker progress_tracker) {
		Envelope2D env_a = new Envelope2D(), env_b = new Envelope2D();
		polyline_a.queryEnvelope2D(env_a);
		envelope_b.queryEnvelope2D(env_b);

		if (envelopeInfContainsEnvelope_(env_a, env_b, tolerance)
				|| envelopeInfContainsEnvelope_(env_b, env_a, tolerance))
			return false;

		if (envelopeInfContainsEnvelope_(env_b, env_a, tolerance))
			return false;

		if (env_b.getHeight() > tolerance && env_b.getWidth() > tolerance)
			return false; // lines cannot overlap areas

		if (env_b.getHeight() <= tolerance && env_b.getWidth() <= tolerance)
			return false; // lines cannot overlap points

		// Treat as polyline
		Polyline polyline_b = new Polyline();
		Point p = new Point();
		envelope_b.queryCornerByVal(0, p);
		polyline_b.startPath(p);
		envelope_b.queryCornerByVal(2, p);
		polyline_b.lineTo(p);
		return linearPathOverlapsLinearPath_(polyline_a, polyline_b, tolerance);
	}
784473
private static boolean polylineDisjointEnvelope_(Polyline polyline_a,
			Envelope envelope_b, double tolerance,
			ProgressTracker progress_tracker) {
		Envelope2D env_a = new Envelope2D(), env_b = new Envelope2D();
		polyline_a.queryEnvelope2D(env_a);
		envelope_b.queryEnvelope2D(env_b);

		if (envelopeInfContainsEnvelope_(env_b, env_a, tolerance))
			return false;

		return !linearPathIntersectsEnvelope_(polyline_a, env_b, tolerance,
				progress_tracker);
	}
138088
function (p, p1, maxIndex, minIndex) {
		var points = this._originalPoints,
			p2, p3;

		minIndex = minIndex || 0;

		// Check all previous line segments (beside the immediately previous) for intersections
		for (var j = maxIndex; j > minIndex; j--) {
			p2 = points[j - 1];
			p3 = points[j];

			if (L.LineUtil.segmentsIntersect(p, p1, p2, p3)) {
				return true;
			}
		}

		return false;
	}
563048
private static boolean polygonRelatePolygon_(Polygon polygon_a,
			Polygon polygon_b, double tolerance, int relation,
			ProgressTracker progress_tracker) {
		switch (relation) {
		case Relation.disjoint:
			return polygonDisjointPolygon_(polygon_a, polygon_b, tolerance,
					progress_tracker);

		case Relation.within:
			return polygonContainsPolygon_(polygon_b, polygon_a, tolerance,
					progress_tracker);

		case Relation.contains:
			return polygonContainsPolygon_(polygon_a, polygon_b, tolerance,
					progress_tracker);

		case Relation.equals:
			return polygonEqualsPolygon_(polygon_a, polygon_b, tolerance,
					progress_tracker);

		case Relation.touches:
			return polygonTouchesPolygon_(polygon_a, polygon_b, tolerance,
					progress_tracker);

		case Relation.overlaps:
			return polygonOverlapsPolygon_(polygon_a, polygon_b, tolerance,
					progress_tracker);

		default:
			break; // warning fix
		}

		return false;
	}
1374963
private static boolean polylineOverlapsPolyline_(Polyline polyline_a,
			Polyline polyline_b, double tolerance,
			ProgressTracker progress_tracker) {
		// Quick rasterize test to see whether the the geometries are disjoint.
		if (tryRasterizedContainsOrDisjoint_(polyline_a, polyline_b, tolerance,
				false) == Relation.disjoint)
			return false;

		return linearPathOverlapsLinearPath_(polyline_a, polyline_b, tolerance);
	}
972654
private static boolean multiPointRelatePoint_(MultiPoint multipoint_a,
			Point point_b, double tolerance, int relation,
			ProgressTracker progress_tracker) {
		switch (relation) {
		case Relation.disjoint:
			return multiPointDisjointPoint_(multipoint_a, point_b, tolerance,
					progress_tracker);

		case Relation.within:
			return multiPointWithinPoint_(multipoint_a, point_b, tolerance,
					progress_tracker);

		case Relation.contains:
			return multiPointContainsPoint_(multipoint_a, point_b, tolerance,
					progress_tracker);

		case Relation.equals:
			return multiPointEqualsPoint_(multipoint_a, point_b, tolerance,
					progress_tracker);

		default:
			break; // warning fix
		}

		return false;
	}
1099777
private static boolean multiPointExactlyEqualsMultiPoint_(
			MultiPoint multipoint_a, MultiPoint multipoint_b, double tolerance,
			ProgressTracker progress_tracker) {
		if (multipoint_a.getPointCount() != multipoint_b.getPointCount())
			return false;

		Point2D ptA = new Point2D(), ptB = new Point2D();
		boolean bAllPointsEqual = true;
		double tolerance_sq = tolerance * tolerance;

		for (int i = 0; i < multipoint_a.getPointCount(); i++) {
			multipoint_a.getXY(i, ptA);
			multipoint_b.getXY(i, ptB);

			if (Point2D.sqrDistance(ptA, ptB) > tolerance_sq) {
				bAllPointsEqual = false;
				break;
			}
		}

		if (!bAllPointsEqual)
			return false;

		return true;
	}
1215292
private static boolean polygonTouchesPolyline_(Polygon polygon_a,
			Polyline polyline_b, double tolerance,
			ProgressTracker progress_tracker) {
		// Quick rasterize test to see whether the the geometries are disjoint,
		// or if one is contained in the other.
		int relation = tryRasterizedContainsOrDisjoint_(polygon_a, polyline_b,
				tolerance, false);

		if (relation == Relation.disjoint || relation == Relation.contains)
			return false;

		return polygonTouchesPolylineImpl_(polygon_a, polyline_b, tolerance,
				progress_tracker);
	}
54631
public static boolean touches(Geometry geometry, Coordinate coordinate) {
		if (Geometry.MULTI_POLYGON.equals(geometry.getGeometryType())) {
			for (int i = 0; i < geometry.getGeometries().length; i++) {
				if (touches(geometry.getGeometries()[i], coordinate)) {
					return true;
				}
			}
			return false;
		} else if (Geometry.POLYGON.equals(geometry.getGeometryType())) {
			for (int i = 0; i < geometry.getGeometries().length; i++) {
				if (touchesLineString(geometry.getGeometries()[i], coordinate)) {
					return true;
				}
			}
			return false;
		} else if (Geometry.MULTI_LINE_STRING.equals(geometry.getGeometryType())) {
			for (int i = 0; i < geometry.getGeometries().length; i++) {
				if (touchesLineString(geometry.getGeometries()[i], coordinate)) {
					return true;
				}
			}
			return false;
		} else if (Geometry.LINEAR_RING.equals(geometry.getGeometryType())) {
			return touchesLineString(geometry, coordinate);
		} else if (Geometry.LINE_STRING.equals(geometry.getGeometryType())) {
			return touchesLineString(geometry, coordinate);
		} else if (Geometry.POINT.equals(geometry.getGeometryType())) {
			return distance(geometry.getCoordinates()[0], coordinate) < PARAM_DEFAULT_DELTA;
		}
		return false;
	}
946640
private static boolean polygonDisjointPoint_(Polygon polygon_a,
			Point point_b, double tolerance, ProgressTracker progress_tracker) {
		PolygonUtils.PiPResult result = PolygonUtils.isPointInPolygon2D(
				polygon_a, point_b, tolerance);

		if (result == PolygonUtils.PiPResult.PiPOutside)
			return true;

		return false;
	}
903306
function(p) {

            if (!p) return false;

            var points = this.points;
            var otherPoints = p.points;

            var numPoints = points.length;
            if (otherPoints.length !== numPoints) return false; // if the two polylines have different number of points, they cannot be equal

            for (var i = 0; i < numPoints; i++) {

                var point = points[i];
                var otherPoint = p.points[i];

                // as soon as an inequality is found in points, return false
                if (!point.equals(otherPoint)) return false;
            }

            // if no inequality found in points, return true
            return true;
        }