[Closed] Evenly divide splines using bezier curves??
I’m wondering what I would need to do in order to take an existing spline, and say “okay, divide this spline into x number of evenly sized segments, and use bezier corners to keep the overall shape of the spline as close to the original as possible.”
I say this fully understanding that it’s probably a lot harder to do than it sounds.
I havent done much in a while, but i think lengthInterp would probably work well. You could first get the number of knots along the spline, over a range of 1.0 e.g .25, .5, .75. Then use lengthInterp to store the positions along the spline using these percentages into an array. Finally push the knot positions into the stored values.
What would be harder is working out the the bezier tangents correctly if a knot has them. Getting that you’d probably need to get the secant, of the predicted shape and push them into it. Interesting challenge
Hm… is seems like there SHOULD be a way to use existing knots along with their inVec/outVec values to determine what the “average” spline passing through them should use for its own knots/inVec/outVec values?
As for the knots themselves, I’m definitely going to be using LengthInterp(). Using just that should get results at least as good as using the “Normalize Spline” modifier. So that’s a good start. Now I just need to figure out the bezier values.
EDIT:
Taking a closer look at this I came up with the following: if you have 3 bezier-corner knots on a spline, and are looking to get rid of the one in the middle but keep the shape (insofar as is possible), then the following values are what you have to work with as things that define the existing bezier curve:
knot1 pos
knot1 outVec posknot2 inVec pos
knot2 position
knot2 outVec posknot3 inVec pos
knot3 posdistance from knot1 pos to knot1 outVec pos
distance from knot1 pos to knot2 inVec pos
distance from knot1 pos to knot2 posangle between (line from knot1 pos to knot2 pos) and (line from knot1 pos to knot1 outVec pos)
angle between (line from knot1 pos to knot2 pos) and (line from knot1 pos to knot2 inVec pos)distance from knot2 pos to knot1 outVec pos
distance from knot2 pos to knot2 inVec posangle between (line from knot2 pos to knot1 pos) and (line from knot2 pos to knot1 outVec pos)
angle between (line from knot2 pos to knot1 pos) and (line from knot2 pos to knot2 inVec pos)distance from knot2 pos to knot2 outVec pos
distance from knot2 pos to knot3 inVec pos
distance from knot2 pos to knot3 posangle between (line from knot2 pos to knot3 pos) and (line from knot2 pos to knot2 outVec pos)
angle between (line from knot2 pos to knot3 pos) and (line from knot2 pos to knot3 inVec pos)distance from knot3 pos to knot2 outVec pos
distance from knot3 pos to knot3 inVec posangle between (line from knot3 pos to knot2 pos) and (line from knot3 pos to knot2 outVec pos)
angle between (line from knot3 pos to knot2 pos) and (line from knot3 pos to knot3 inVec pos)
So I was thinking this might be a good starting point…
So lets’ see…
First off, tried experimenting with a simple circle, radius 100 (generic units), converted to an editable spline. I determined that with the 4 knots, the distance of the in and out vectors comes to 55.1786. Obviously, the angle of each bezier “handle” is at 45 degrees to the lines between each knot and its neighbors.
Removing one of the knots, I lengthened each of the neighboring bezier handles to 133.3333. The midpoint of the spline now matches the position of the deleted knot. The angle of the handles are 90 degrees to the newly neighboring knots (or still at 45 degrees to the deleted knot).
Now, I realize that the new length of the adjusted splines is exactly 4/3 the radius of the circle. I’m not sure exactly how to figure the 55.1786 length of the original splines, but the new length is 2.4164 times the original. I tried that ratio with different sized circles and it always gives the desired result, but I am similarly unable to determine the significance of 2.4164.
If anyone who knows more about math can explain some of these things to me, it would be very helpful!
Also, I went ahead and set up a program to collect all of the various values I mentioned in my previous post. Unfortunately, I still don’t really know what to do with them.
array_KnotData = #()
theShape = $
-- Special thanks to prettyPixel
fn lineLineAngle pA pB pC pD =
(
local vAB = pB - pA
local vCD = pD - pC
local angle = acos (dot (normalize vAB) (normalize vCD))
if angle < 90.0 then angle else (180.0 - angle)
)
for s = 1 to numSplines theShape do
(
append array_KnotData #()
for k = 1 to numKnots theShape s do
(
append array_KnotData[s] #()
local kPrev, oPrev, iThis
local dist_kPoP, dist_kPiT, dist_kPkT, dist_kToP, dist_kTiT
local angle_kPoP, angle_kPiT, angle_kToP, angle_kTiT
kThis = getKnotPoint theShape s k -- current knot point
local oThis, iNext, kNext
local dist_kToT, dist_kTiN, dist_kTkN, dist_kNoT, dist_kNiN
local angle_kToT, angle_kTiN, angle_kNoT, angle_kNiN
if k > 1 do
(
kPrev = getKnotPoint theShape s (k - 1) -- previous knot point
oPrev = getOutVec theShape s (k - 1) -- outVector of previous knot point
iThis = getInVec theShape s k -- inVector of current knot point
dist_kPoP = distance kPrev oPrev
dist_kPiT = distance kPrev iThis
dist_kPkT = distance kPrev kThis
dist_kToP = distance kThis oPrev
dist_kTiT = distance kThis iThis
angle_kPoP = lineLineAngle kPrev oPrev kPrev kThis
angle_kPiT = lineLineAngle kPrev iThis kPrev kThis
angle_kToP = lineLineAngle kThis oPrev kThis kPrev
angle_kTiT = lineLineAngle kThis iThis kThis kPrev
)
if k < (numKnots theShape s) do
(
oThis = getOutVec theShape s k -- outVector of current knot point
iNext = getKnotPoint theShape s (k + 1) -- inVector of next knot point
kNext = getKnotPoint theShape s (k + 1) -- next knot point
dist_kToT = distance kThis oThis
dist_kTiN = distance kThis iNext
dist_kTkN = distance kThis kNext
dist_kNoT = distance kNext oThis
dist_kNiN = distance kNext iNext
angle_kToT = lineLineAngle kThis oThis kThis kNext
angle_kTiN = lineLineAngle kThis iNext kThis kNext
angle_kNoT = lineLineAngle kNext oThis kNext kThis
angle_kNiN = lineLineAngle kNext iNext kNext kThis
)
append array_KnotData[s][k] #(kPrev, oPrev, iThis)
append array_KnotData[s][k] #(dist_kPoP, dist_kPiT, dist_kPkT, dist_kToP, dist_kTiT)
append array_KnotData[s][k] #(angle_kPoP, angle_kPiT, angle_kToP, angle_kTiT)
append array_KnotData[s][k] kThis
append array_KnotData[s][k] #(oThis, iNext, kNext)
append array_KnotData[s][k] #(dist_kToT, dist_kTiN, dist_kTkN, dist_kNoT, dist_kNiN)
append array_KnotData[s][k] #(angle_kToT, angle_kTiN, angle_kNoT, angle_kNiN)
)
)
for s = 1 to array_KnotData.count do
(
for k = 1 to array_KnotData[s].count do (format "[%][%]: %
" s k array_KnotData[s][k])
)