Does dynamo have anything for the title? I ended up doing a right angle lines off the two curves. Clashing them with the surface between the two curves and getting the center points of the lines, organizing and running a nurbs curve through it (not sure how accurate it is). However my two lines were more consistent between each other. What if you had two crazy lines like in the post below? Do we have this circle fitting? distance field on a mesh?
Little left of the title. What I came up with to try use the average curve to get sawcut lines along a path. But curious if you have more inconsistent parallel lines. Floors_Sawcut segments along path.dyn (228.4 KB)
R23 Test Paths.rvt (1.3 MB)
Lofting between the two curves and finding the isocurve is likely the ‘easy’ path, but that won’t work in all situations.
You could also try converting both to nurbs curves and building from the average weighting, but that may not work on all cases.
Sampling along curve A and getting the mid point to the closest point on curve B could also work.
Getting the medial axis and finding the shortest path works well, but could be inefficient.
One solution I didn’t see there is, getting a UV map of the distance from the curves within the same domain and finding the ‘common’ values within the surface… could be the most effective overall but the math on it might not be as straightforward as I would like.
Hi,
a trial by calculating an approximate curve (with scipy), then a search along the perpendiculars for points equidistant from the input curves.
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import numpy as np
from scipy.interpolate import interp1d
from scipy.ndimage import uniform_filter1d
curveA, curveB = IN[0]
plane = Plane.ByOriginNormal(Point.ByCoordinates(0, 0 , 0), Vector.ByCoordinates(0,0,1))
# ensure curves are Z zero
curveA = curveA.PullOntoPlane(plane)
curveB = curveB.PullOntoPlane(plane)
ptCurveA = [curveA.PointAtParameter(n) for n in np.linspace(0, 1, num=500)]
ptCurveB = [curveB.PointAtParameter(n) for n in np.linspace(0, 1, num=500)]
# merge, flatten points and keeping order
pts = [pt for pairPts in zip(ptCurveA,ptCurveB) for pt in pairPts]
data = [[int(p.X), int(p.Y)] for p in pts]
x, y = [i for i in zip(*data)]
# compute the arithmetic average with scipy.ndimage.uniform_filter1d
y_smooth = uniform_filter1d(y,size=5, mode='wrap')
x_smooth = uniform_filter1d(x,size=5, mode='wrap')
rays = []
mid_Pts = []
ray_length = 6000 # example in millimeter
# compute an approximative average curve
pts_uniform = [Point.ByCoordinates(x, y , 0) for x, y in zip(x_smooth, y_smooth)]
pts_uniform_iter = iter(pts_uniform[:])
dsPoints = [Point.ByCoordinates((pta.X + ptb.X) / 2, (pta.Y + ptb.Y) / 2, 0) for pta, ptb in zip(pts_uniform_iter, pts_uniform_iter)]
# remove extra points
dsPoints = dsPoints[1:-1]
aprox_average_curve = PolyCurve.ByPoints(dsPoints, False)
# with this curve compute an new average curve by normal curve intersection (ray) and compute middle points
for n in np.linspace(0, 1, num=100):
normal = aprox_average_curve.NormalAtParameter(n)
pt = aprox_average_curve.PointAtParameter(n)
ray_line = Line.ByStartPointDirectionLength(pt, normal, ray_length)
ray_line = ray_line.Translate(normal.Reverse(), ray_length / 2)
if ray_line.DoesIntersect(curveA) and ray_line.DoesIntersect(curveB):
ptInterA = ray_line.Intersect(curveA)[0]
ptInterB = ray_line.Intersect(curveB)[0]
midpt = Point.ByCoordinates((ptInterA.X + ptInterB.X) / 2, (ptInterA.Y + ptInterB.Y) / 2, 0)
rays.append(ray_line)
mid_Pts.append(midpt)
OUT = rays, PolyCurve.ByPoints(mid_Pts, False)