[Closed] Knot re-ordering problem
Hi Everybody,
I’ve been trying to come up with a script that takes an input spline, and rearranges the knots according to their distance from each other, with the first knot being fixed, then the next nearest knot, then the next nearest to that, etc…
So far I’ve come up with this:
(
originalpointarray = for i = 1 to (numknots $ 1) collect (getknotpoint $ 1 i)
pointarray = originalpointarray
newpoints = #()
newpoint = [0,0,0]
indexcheck = 0
for i = 1 to originalpointarray.count do
(
checkdist = 9999.0
--if pointarray.count == 1 do continue
for j = 1 to pointarray.count do
(
if pointarray[i] == pointarray[j] do continue
newdist = distance pointarray[i] pointarray[j]
if newdist <= checkdist then
(
checkdist = newdist
newpoint = pointarray[j]
indexcheck = j
)
)
append newpoints newpoint
deleteitem pointarray indexcheck
)
print newpoints
)
This takes a selected spline, and tests each point against an array of the same points, identifying the closest one, then deleting that value from the array that contains the remaining points to be checked against. It finally outputs the new ordered array of knots…
But still no joy… I have a feeling I’m missing something!
Any pointers would be greatly appreciated.
Archtic.
Here’s a revision that’s a bit different… I build an “ToPoint” index array that lets you know to which point is the shortest from the current point. I also use a bitarray #{} as a flagging system to see if the point has been used or not.
I’m then constructing a new spline from the data.
(
originalpointarray = for i = 1 to (numknots $ 1) collect (getknotpoint $ 1 i)
ToPointArray = #( 1 )
PointUsed = #{ 1 }
for i = 2 to originalpointarray.count do
(
local checkdist = 999999.0
local ShortestPoint = 0
local newdist
for j = 1 to originalpointarray.count do
(
if (( i != j ) and ( not PointUsed[ j ] )) then
(
newdist = distance originalpointarray[ToPointArray[ToPointArray.count]] originalpointarray[j]
if (newdist <= checkdist) then
(
checkdist = newdist
ShortestPoint = j
)
)
)
PointUsed[ ShortestPoint ] = true
append ToPointArray ShortestPoint
)
tnShape = SplineShape()
addNewSpline tnShape
for i = 1 to ToPointArray.count do
(
addKnot tnShape 1 #corner #line originalpointarray[ ToPointArray[i] ]
)
updateShape tnShape
)
Looking at yours again… don’t you want to compare the distance from the orginial array and the remaining ones? Also when you set an Array value to a variable in MaxScript, you get a reference to the array, not a unique value. So you are effectively deleteing Items from a single array in memory
Listener
Array1= #(4,5,6)
#(4, 5, 6)
Array2 = Array1
#(4, 5, 6)
Array1[2]=10
10
Array2
#(4, 10, 6)
Thanks Kramsurfer, appreciate your help on this. The flagging system is a useful little routine, and yes, I forgot about array reference… which would explain some of the problems!
I’ve just been runing your script on a few examples, and have got some weired behaviour… for instance:
setting originalpointarray as #([1714.34,-1424.13,0], [2827.51,-875.123,0], [2102.58,-1236.07,0], [3236.99,-671.901,0])
gives a runtime error that shortestpoint is 0… so i’ll try and tease that one out…
and setting originalpointarray as #([898.417,-1642.51,0], [2691.02,-699.199,0], [1432.25,-1345.26,0], [2939.74,-565.74,0], [3327.98,-362.518,0])
produces the new line: #([898.417,-1642.51,0], [1432.25,-1345.26,0], [2691.02,-699.199,0], [3327.98,-362.518,0], [2939.74,-565.74,0])
which has the correct order of the last two points transposed… odd…
I’ll post some code when I’ve had time to work on it. Thanks again.
Ok, think I’ve fixed it:
(
originalpointarray = for i = 1 to (numknots $ 1) collect (getknotpoint $ 1 i)
ToPointArray = #(1)
PointUsed = #{ 1 }
for i = 2 to originalpointarray.count do
(
local checkdist = 999999.0
local ShortestPoint = 0
local newdist
for j = 1 to originalpointarray.count do
(
if ((originalpointarray[topointarray[topointarray.count]] != originalpointarray[j]) and ( not pointused[j])) then --(( i != j ) and ( not PointUsed[ j ] )) then
(
newdist = distance originalpointarray[topointarray[topointarray.count]] originalpointarray[j]
if (newdist <= checkdist) then
(
checkdist = newdist
ShortestPoint = j
)
)
)
PointUsed[ ShortestPoint ] = true
append ToPointArray ShortestPoint
)
tnShape = SplineShape()
addNewSpline tnShape
for i = 1 to ToPointArray.count do
(
addKnot tnShape 1 #corner #line originalpointarray[ ToPointArray[i] ]
)
updateShape tnShape
)
I changed the test i != j to do a comparison between the point3 values instead… this seems to have worked out the kinks…
Thanks again.
A.
ahhh. yeah the current point makes more sense… good job… I’ll update this in my Snibbit library… thanks…