func()

in s2/contains_point_query.go [87:136]


func (q *ContainsPointQuery) shapeContains(clipped *clippedShape, center, p Point) bool {
	inside := clipped.containsCenter
	numEdges := clipped.numEdges()
	if numEdges <= 0 {
		return inside
	}

	shape := q.index.Shape(clipped.shapeID)
	if shape.Dimension() != 2 {
		// Points and polylines can be ignored unless the vertex model is Closed.
		if q.model != VertexModelClosed {
			return false
		}

		// Otherwise, the point is contained if and only if it matches a vertex.
		for _, edgeID := range clipped.edges {
			edge := shape.Edge(edgeID)
			if edge.V0 == p || edge.V1 == p {
				return true
			}
		}
		return false
	}

	// Test containment by drawing a line segment from the cell center to the
	// given point and counting edge crossings.
	crosser := NewEdgeCrosser(center, p)
	for _, edgeID := range clipped.edges {
		edge := shape.Edge(edgeID)
		sign := crosser.CrossingSign(edge.V0, edge.V1)
		if sign == DoNotCross {
			continue
		}
		if sign == MaybeCross {
			// For the Open and Closed models, check whether p is a vertex.
			if q.model != VertexModelSemiOpen && (edge.V0 == p || edge.V1 == p) {
				return (q.model == VertexModelClosed)
			}
			// C++ plays fast and loose with the int <-> bool conversions here.
			if VertexCrossing(crosser.a, crosser.b, edge.V0, edge.V1) {
				sign = Cross
			} else {
				sign = DoNotCross
			}
		}
		inside = inside != (sign == Cross)
	}

	return inside
}