Notifications
Clear all

[Closed] Qsort???

Hello,

Im having some problems with qsort and was wondering if anyone could steer me in the right direction?!

What I am trying to do is write a script that can select a point within an array – collect the points around the selected point into a second array then link the points in the second array with a line to form a region around the original point.

[size=2]The problem i am having is that when i try linking the points with a line:[/size]

 
fn bind_mid a = -- a is the array
(
ss = splineshape pos:a[1]
addnewspline ss
 
for i in a do
(
addknot ss 1 #smooth #curve i
)
close ss 1
updateshape ss
ss
)

Because my points in array ‘a’ are not ordered the line intersects itself sometimes and does not form a nice boundary around the original point as I would like.

I have tried using qsort to resolve this but it is confusing me! It was my intention to select the northmost point from the array ‘a’ then sort/collect the points in a systematic clockwise manner so that when i link the points with the code above they form empty regions.

I have managed to use qsort to find the northmost point in the array using this:


fn comparefn v1 v2 =
(
local d = v1.pos.y
case of
(
(d < v2.pos.y):-1
(d>v2.pos.y):1
default:0
)
)
qsort a comparefn
 

I thought that I could use something like this to either sort the full array or if that is not achievable just find the next point closest to the northmost point??

If anybody can help me or even just point me in the right direction I would really appresiate it!

Thanks,

Danny

10 Replies

Is the Arrayed data 2D or 3D?

I’m assuming 2D as you wish to bound with a spline…
If your working in 2D:

You may want index them by degrees from the origin based on real world Coords.
See the atan2() function for a quick way to get the angle between to points.
Then sort those points based on angle, draw and close spline…

If you sorting in 3D data to bound with a 2d object…
ummm… good luck :-/

Yeh sorry I forgot to mention that, I am doing 2d.

I will have a look that that now, Hopefully that will sort out my problems!
Cheers.

Is there anyway I could use atan2 but change the origin to a new point?

If this is possible I think it would solve my problem easily.

yeah… like so

– in the listener
p1=[20,20]
[20,20]
p2=[10,10]
[10,10]
atan2 ( p1.x-p2.x ) ( p1.y – p2.y )
45.0
p2=[10,20]
[10,20]
atan2 ( p1.x-p2.x ) ( p1.y – p2.y )
90.0

It’ll give you the relative angle from p1, feed your arrayed values into p2…

Good luck…

you are a hero! That sounds like it will work like a dream.

Cheers

Yep that worked!! Thanks again.

 fn comparefn v1 v2 = 
(
local d = atan2 (($box01.pos.x) - (v1.pos.x)) (($box01.pos.y) - (v1.pos.y))
local e = atan2 (($box01.pos.x) - (v2.pos.x)) (($box01.pos.y) - (v2.pos.y))
case of
(
(d>e):-1
(d<e):1
default:0
)
)
qsort temp comparefn 

Ok I have another problem now. The function above works fine when i plug in $box01 into the actual function.

However what i need to be able to do is loop through an array of boxes and perform the same proceedure on each box; effectivly i need to be able to have another variable in the function.

something like this maybe:

 fn comparefn v1 v2 i = 
(
local d = atan2 ((i.pos.x) - (v1.pos.x)) ((i.pos.y) - (v1.pos.y))
local e = atan2 ((i.pos.x) - (v2.pos.x)) ((i.pos.y) - (v2.pos.y))
case of
(
(d>e):-1
(d<e):1
default:0
)
)

This way when i loop through the boxes i can change the origin of the world coordinates. Is there a way of adding a third variable without generating the error message:
“– Argument count error: qsort wanted 2, got 3”?

Are you perhaps doing:

qsort temp comparefn $box01

instead of:

qsort temp (comparefn $box01)

I may be wrong but i dont think that is the problem.

I will try to explain what I am trying to do slightly better:

I am starting out with an array of boxes randomly positioned.
I am looping through the boxes to find all other boxes within a given radius and storing these in an array called temp.
Finally I am trying to connect up all the boxes within array ‘temp’ to form a boundry around the original box (in the loop).

To do this final step I have had to find a way to sort the boxes in ‘temp’ so that i draw a boundary which does not intersect with itself.

I am using qsort and I have written the function above to try and sort the array as required.

The problem I currently have is that whilst this function works if i am just evaluating $box01:

 [left]fn comparefn v1 v2 = 

(
local d = atan2 (($box01.pos.x) - (v1.pos.x)) (($box01.pos.y) - (v1.pos.y))
local e = atan2 (($box01.pos.x) - (v2.pos.x)) (($box01.pos.y) - (v2.pos.y))
case of
(
(d>e):-1
(d<e):1
default:0
)
)
qsort temp comparefn 

[/left]

[left]It does not alow me to loop through the remaining boxes to do the same procedure. I thought perhaps I could do something like this:[/left]

[left]

 [left]fn comparefn v1 v2 i = 

(
local d = atan2 ((i.pos.x) - (v1.pos.x)) ((i.pos.y) - (v1.pos.y))
local e = atan2 ((i.pos.x) - (v2.pos.x)) ((i.pos.y) - (v2.pos.y))
case of
(
(d>e):-1
(d<e):1
default:0
)
)
[left]qsort temp (comparefn i)[/left]

[/left]

[/left]

[left]Where i is the box being evaluated in the loop:[/left]

[left]

 [left]for i in allboxes do[/left]
[left]([/left]
.... [left]qsort temp (comparefn i)[/left]
[left]....[/left]
[left])[/left]

[/left]

[left]However this does not work, therefore the question i am asking is can i use a similar method that allows me to loop through every box and draw its non intersecting boundary. [/left]

[left]i hope that is more clear. Im sure i am pretty close to sorting this out but i cant seem to figure out what i am doing wrong?? any ideas?[/left]

Page 1 / 2