Jump to content

Tangent on a polyline control point

Recommended Posts

I am working on a script that converts Vectorworks polylines into SVG paths and I have managed to "translate" everything except for the cubic splines vertexes.

I know that a cubic splines vertex control point is equivalent to two bezier vertexes, simply crossing the tangent lines, see figure.


The problem is: how I determine the tangent exactly in a polyline vertex?

The only way seems to go with this one…

def vs.PointAlongPoly(h, dist):
    return (BOOLEAN, pt, tangent)

…but I cannot know what distance the control point has.

Furthermore, testing this (and the similar PointAlongPolyN), I get inaccurate results placing of the points on the curve.

I know (from past experiences) that this function calculates distances on the poly just "polygonizing" the curve, but the conversion resolution is unknown (and not settable).



Thank you for the help.


Share this post

Link to post

I have found a way, it works, but has some inaccuracy (due to the PointAlongPoly precision), but I can leave with it.

Of course, if there is a better solution it will welcome!

import math

def angleBetweenPoints(p1, p2):
#given 2 point coordinates it retrieves the angle of the line passing between them
	orientation = None
	if p1[0]==p2[0]:
		if p1[1] <= p2[1]:
			orientation = 90
			orientation = 270
	if p1[1]==p2[1]:
		if p1[0] <= p2[0]:
			orientation =  0
			orientation = 180
	if (p1[0]!=p2[0]) and (p1[1]!=p2[1]):
		if p1[0]<p2[0]:
			quadrant = 0
			quadrant = 180
		orientation = quadrant+vs.Rad2Deg(vs.ArcTan((p1[1]-p2[1])/(p1[0]-p2[0])))
	return orientation

def tangentAtIndex(h, index, resolution):
	minDist = 1e308 #a very large number initially
	tangent = None
	ptVt, vertexType, arcRadius = vs.GetPolylineVertex(h, index)
	ht = vs.ConvertToPolygon(h, resolution)
	#cycle searching min distance
	for i in range(1, vs.GetVertNum(ht)+1):
		pi = vs.GetPolyPt(ht, i)
		dist = vs.Distance(ptVt[0], ptVt[1], pi[0], pi[1])
		if dist < minDist:
			minDist = dist
			if (i > 1) and (i+1 < vs.GetVertNum(ht)):
				pt1 = vs.GetPolyPt(ht, i-1)
				pt3 = vs.GetPolyPt(ht, i+1)
				c = vs.ThreePtCenter(pt1, pi, pt3)
				tangent = angleBetweenPoints(c, pi)+90
				if i == 1:
					#angle between 1 and 2
					pt1 = vs.GetPolyPt(ht, 1)
					pt2 = vs.GetPolyPt(ht, 2)
					tangent = angleBetweenPoints(pt1, pt2)
				if i == vs.GetVertNum(ht):
					#angle between latest and latest-1
					pt1 = vs.GetPolyPt(ht, vs.GetVertNum(ht))
					pt2 = vs.GetPolyPt(ht, vs.GetVertNum(ht)-1)
					tangent = angleBetweenPoints(pt1, pt2)

	return tangent

#test a selected polyline

h = vs.FSActLayer()

for i in range(1, vs.GetVertNum(h)+1):

	t = tangentAtIndex(h, i, 512)
	p, vertexType, arcRadius = vs.GetPolylineVertex(h, i)
	vs.Locus(p[0], p[1])
	vs.MoveTo(p[0]-1*math.cos(vs.Deg2Rad(t)), p[1]-1*math.sin(vs.Deg2Rad(t)))
	vs.LineTo(p[0]+1*math.cos(vs.Deg2Rad(t)), p[1]+1*math.sin(vs.Deg2Rad(t)))


Share this post

Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


7150 Riverwood Drive, Columbia, Maryland 21046, USA   |   Contact Us:   410-290-5114


© 2018 Vectorworks, Inc. All Rights Reserved. Vectorworks, Inc. is part of the Nemetschek Group.

  • Create New...