예제 #1
0
파일: polyline.go 프로젝트: tanema/amore
/** Calculate line boundary points.
 *
 * Sketch:
 *
 *     uh1___uh2
 *      .'   '.
 *    .'   q   '.
 *  .'   '   '   '.
 *.'   '  .'.  '   '.
 *   '  .' ul'.  '
 * p  .'       '.  r
 *
 *
 * ul can be found as above, uh1 and uh2 are much simpler:
 *
 * uh1 = q + ns * w/2, uh2 = q + nt * w/2
 */
func (polyline *polyLine) renderBevelEdge(sleeve, current, next mgl32.Vec2) {
	t := next.Sub(current)
	len_t := t.Len()

	det := determinant(sleeve, t)
	if mgl32.Abs(det)/(sleeve.Len()*len_t) < LINES_PARALLEL_EPS && sleeve.Dot(t) > 0 {
		// lines parallel, compute as u1 = q + ns * w/2, u2 = q - ns * w/2
		n := getNormal(t, polyline.halfwidth/len_t)
		polyline.normals = append(polyline.normals, n)
		polyline.normals = append(polyline.normals, n.Mul(-1))
		polyline.generateEdges(current, 2)
		return // early out
	}

	// cramers rule
	sleeve_normal := getNormal(sleeve, polyline.halfwidth/sleeve.Len())
	nt := getNormal(t, polyline.halfwidth/len_t)
	lambda := determinant(nt.Sub(sleeve_normal), t) / det
	d := sleeve_normal.Add(sleeve.Mul(lambda))

	if det > 0 { // 'left' turn -> intersection on the top
		polyline.normals = append(polyline.normals, d)
		polyline.normals = append(polyline.normals, sleeve_normal.Mul(-1))
		polyline.normals = append(polyline.normals, d)
		polyline.normals = append(polyline.normals, nt.Mul(-1))
	} else {
		polyline.normals = append(polyline.normals, sleeve_normal)
		polyline.normals = append(polyline.normals, d.Mul(-1))
		polyline.normals = append(polyline.normals, nt)
		polyline.normals = append(polyline.normals, d.Mul(-1))
	}
	polyline.generateEdges(current, 4)
}
예제 #2
0
파일: polyline.go 프로젝트: tanema/amore
/** Calculate line boundary points.
 *
 * Sketch:
 *
 *              u1
 * -------------+---...___
 *              |         ```'''--  ---
 * p- - - - - - q- - . _ _           | w/2
 *              |          ` ' ' r   +
 * -------------+---...___           | w/2
 *              u2         ```'''-- ---
 *
 * u1 and u2 depend on four things:
 *   - the half line width w/2
 *   - the previous line vertex p
 *   - the current line vertex q
 *   - the next line vertex r
 *
 * u1/u2 are the intersection points of the parallel lines to p-q and q-r,
 * i.e. the point where
 *
 *    (q + w/2 * ns) + lambda * (q - p) = (q + w/2 * nt) + mu * (r - q)   (u1)
 *    (q - w/2 * ns) + lambda * (q - p) = (q - w/2 * nt) + mu * (r - q)   (u2)
 *
 * with nt,nt being the normals on the segments s = p-q and t = q-r,
 *
 *    ns = perp(s) / |s|
 *    nt = perp(t) / |t|.
 *
 * Using the linear equation system (similar for u2)
 *
 *         q + w/2 * ns + lambda * s - (q + w/2 * nt + mu * t) = 0                 (u1)
 *    <=>  q-q + lambda * s - mu * t                          = (nt - ns) * w/2
 *    <=>  lambda * s   - mu * t                              = (nt - ns) * w/2
 *
 * the intersection points can be efficiently calculated using Cramer's rule.
 */
func (polyline *polyLine) renderMiterEdge(sleeve, current, next mgl32.Vec2) {
	sleeve_normal := getNormal(sleeve, polyline.halfwidth/sleeve.Len())
	t := next.Sub(current)
	len_t := t.Len()

	det := determinant(sleeve, t)
	// lines parallel, compute as u1 = q + ns * w/2, u2 = q - ns * w/2
	if mgl32.Abs(det)/(sleeve.Len()*len_t) < LINES_PARALLEL_EPS && sleeve.Dot(t) > 0 {
		polyline.normals = append(polyline.normals, sleeve_normal)
		polyline.normals = append(polyline.normals, sleeve_normal.Mul(-1))
	} else {
		// cramers rule
		nt := getNormal(t, polyline.halfwidth/len_t)
		lambda := determinant(nt.Sub(sleeve_normal), t) / det
		d := sleeve_normal.Add(sleeve.Mul(lambda))

		polyline.normals = append(polyline.normals, d)
		polyline.normals = append(polyline.normals, d.Mul(-1))
	}
	polyline.generateEdges(current, 2)
}