Beispiel #1
0
func EdgeInterpolateAtDistance(ax s1.Angle, a, b Point, ab s1.Angle) Point {
	axRad := ax.Radians()
	abRad := ab.Radians()
	f := math.Sin(axRad) / math.Sin(abRad)
	e := math.Cos(axRad) - f*math.Cos(abRad)
	v0 := a.Mul(e)
	v1 := b.Mul(f)
	return Point{v0.Add(v1).Normalize()}
}
Beispiel #2
0
// radiusToHeight converts an s1.Angle into the height of the cap.
func radiusToHeight(r s1.Angle) float64 {
	if r.Radians() < 0 {
		return emptyHeight
	}
	if r.Radians() >= math.Pi {
		return fullHeight
	}
	// The height of the cap can be computed as 1 - cos(r), but this isn't very
	// accurate for angles close to zero (where cos(r) is almost 1). The
	// formula below has much better precision.
	d := math.Sin(0.5 * r.Radians())
	return 2 * d * d

}
Beispiel #3
0
func (p *Polygon) InternalClipPolyline(invert bool, a *Polyline, out *[]*Polyline, mergeRadius s1.Angle) {
	// Clip the polyline A to the interior of this polygon.
	// The resulting polyline(s) will be appended to "out".
	// If invert is true, we clip A to the exterior of this polygon
	// instead. Vertices will be dropped such that adjacent vertices
	// will not be closer than "mergeRadius".
	//
	// We do the intersection/subtraction by walking the polyline edges.
	// For each edge, we compute all intersections with the polygon
	// boundary and sort them in increasing order of distance along that
	// edge. We then divide the intersection points into pairs, and
	// output a clipped polyline segment for each one.
	// We keep track of whether we're inside or outside of the polygon
	// at all times to decide which segments to output.
	var intersections IntersectionSet
	var vertices []Point
	index := NewPolygonIndex(p, false)
	n := a.NumVertices()
	inside := p.ContainsPoint(a.Vertex(0)) != invert
	for j := 0; j < n-1; j++ {
		a0 := a.Vertex(j)
		a1 := a.Vertex(j + 1)
		ClipEdge(a0, a1, index, true, &intersections)
		if inside {
			intersections = append(intersections, FloatPointPair{0, a0})
		}
		inside = (len(intersections) & 1) != 0
		if inside {
			intersections = append(intersections, FloatPointPair{1, a1})
		}
		sort.Sort(intersections)
		// At this point we have a sorted array of vertex pairs
		// representing the edge(s) obtained after clipping (a0,a1)
		// against the polygon.
		for k := 0; k < len(intersections); k += 2 {
			if intersections[k] == intersections[k+1] {
				continue
			}
			v0 := intersections[k].second
			v1 := intersections[k+1].second

			// If the gap from the previous vertex to this one is
			// large enough, start a new polyline.
			if len(vertices) > 0 && vertices[len(vertices)-1].Angle(v0.Vector).Radians() > mergeRadius.Radians() {
				*out = append(*out, PolylineFromPoints(vertices))
				vertices = []Point{}
			}
			// Append this segment to the current polyline,
			// ignoring any vertices that are too close to the
			// previous vertex.
			if len(vertices) == 0 {
				vertices = append(vertices, v0)
			}
			if vertices[len(vertices)-1].Angle(v1.Vector).Radians() > mergeRadius.Radians() {
				vertices = append(vertices, v1)
			}
		}
		intersections = IntersectionSet{}
	}
	if len(vertices) > 0 {
		*out = append(*out, PolylineFromPoints(vertices))
	}
}