Page 1 of 1
Vector Drawing + one point
Posted: Sun Jan 28, 2024 10:05 pm
by jamirokwai
Hi there,
I am trying to create some polygon-drawings using a canvas and the vector-lib.
In the following code, I add a few points, creating a white polygon on a black background. So far so good.
After clicking once in the window, a new point will be added to the bottom right. So far so good.
But: I need to have the point-coordinates sorted, so there there are no intersected lines.
I fiddled around with some algorithms, but can't quite get my head around them :-/
So, here is my code.
Thanks for any hints and tips!
Code: Select all
EnableExplicit
Structure polygon_point_struct
id.w
x.w
y.w
EndStructure
Global NewList polygons.polygon_point_struct()
Global event
Procedure MakePolygons()
AddElement(polygons())
With polygons()
\id = 0
\x = 100
\y = 100
EndWith
AddElement(polygons())
With polygons()
\id = 1
\x = 150
\y = 250
EndWith
AddElement(polygons())
With polygons()
\id = 2
\x = 200
\y = 200
EndWith
AddElement(polygons())
With polygons()
\id = 3
\x = 240
\y = 80
EndWith
AddElement(polygons())
With polygons()
\id = 4
\x = 130
\y = 60
EndWith
EndProcedure
Procedure DrawPolygons()
Protected start_x, start_y
SetGadgetAttribute(0, #PB_Canvas_Image, ImageID(0))
If StartVectorDrawing(CanvasVectorOutput(0))
ForEach polygons()
VectorSourceColor(RGBA(255,255,255,255))
ForEach polygons()
; draw lines between all the dots
With polygons()
; first dot? save x/y for later
If polygons()\id = 0
start_x = \x
start_y = \y
MovePathCursor(start_x, start_y)
EndIf
AddPathLine(\x, \y)
StrokePath(1)
; move to the end of the last line
MovePathCursor(\x, \y)
EndWith
Next
; am Ende noch die letzte Linie schließen
AddPathLine(start_x, start_y)
StrokePath(1)
Next
StopVectorDrawing()
EndIf
EndProcedure
CreateImage(0, 500, 500, 32, #Black)
OpenWindow(0, 100, 100, 500, 500, "Test")
CanvasGadget(0, 0, 0, 500, 500)
SetGadgetAttribute(0, #PB_Canvas_Image, ImageID(0))
MakePolygons()
DrawPolygons()
Repeat
event = WaitWindowEvent(20)
If event = #PB_Event_CloseWindow
FreeImage(0)
FreeGadget(0)
CloseWindow(0)
End
EndIf
If event = #PB_Event_Gadget
If EventGadget() = 0 And EventType() = #PB_EventType_LeftClick
AddElement(polygons())
With polygons()
\id = 5
\x = 375
\y = 385
EndWith
DrawPolygons()
EndIf
EndIf
ForEver
Re: Vector Drawing + one point
Posted: Sun Jan 28, 2024 10:16 pm
by infratec
For me it's not 100% clear what you want to achieve.
Can you show a drawing what result you expect?
Re: Vector Drawing + one point
Posted: Mon Jan 29, 2024 7:19 am
by STARGÅTE
jamirokwai wants to add a polygon corner in such a way that the polygon keeps convex or at least a polygon without intersections.
@jamirokwai: You can calculate the distance between the new point and all other polygon point pairs and check, for which pair the distance is minimal. Here you can add the new point in between.
Re: Vector Drawing + one point
Posted: Mon Jan 29, 2024 7:20 am
by jamirokwai
infratec wrote: Sun Jan 28, 2024 10:16 pm
For me it's not 100% clear what you want to achieve.
Can you show a drawing what result you expect?
Sure.
I've been trying to wrap my head around Jarvis and Graham. Maybe, it was too late on a busy Sunday, but I couldn't catch it
This is the original polygon:
Here, I added a point to the end of the list.
After having sorted the points, it should look like this.

Re: Vector Drawing + one point
Posted: Mon Jan 29, 2024 7:22 am
by jamirokwai
STARGÅTE wrote: Mon Jan 29, 2024 7:19 am
jamirokwai wants to add a polygon corner in such a way that the polygon keeps convex or at least a polygon without intersections.
Yes, that's it. See the images as well.
STARGÅTE wrote: Mon Jan 29, 2024 7:19 am
@jamirokwai: You can calculate the distance between the new point and all other polygon point pairs and check, for which pair the distance is minimal. Here you can add the new point in between.
Ok. That's a great hint. I will try the distances. Thanks!
Re: Vector Drawing + one point
Posted: Mon Jan 29, 2024 10:32 am
by jamirokwai
So, the distances work (kind of

)
The first two added points look great, but the last one screws it up.
Code: Select all
EnableExplicit
Structure polygon_point_struct
id.w
x.w
y.w
EndStructure
Global NewList polygons.polygon_point_struct()
Global event
Procedure MakePolygons()
AddElement(polygons())
With polygons()
\id = 0
\x = 100
\y = 100
EndWith
AddElement(polygons())
With polygons()
\id = 1
\x = 150
\y = 250
EndWith
AddElement(polygons())
With polygons()
\id = 2
\x = 200
\y = 200
EndWith
AddElement(polygons())
With polygons()
\id = 3
\x = 240
\y = 80
EndWith
AddElement(polygons())
With polygons()
\id = 4
\x = 130
\y = 60
EndWith
EndProcedure
Procedure DrawPolygons()
Protected start_x, start_y
SetGadgetAttribute(0, #PB_Canvas_Image, ImageID(0))
If StartVectorDrawing(CanvasVectorOutput(0))
ForEach polygons()
VectorSourceColor(RGBA(255,255,255,255))
ForEach polygons()
; draw lines between all the dots
With polygons()
; first dot? save x/y for later
If polygons()\id = 0
start_x = \x
start_y = \y
MovePathCursor(start_x, start_y)
EndIf
AddPathLine(\x, \y)
StrokePath(1)
; move to the end of the last line
MovePathCursor(\x, \y)
EndWith
Next
; am Ende noch die letzte Linie schließen
AddPathLine(start_x, start_y)
StrokePath(1)
Next
StopVectorDrawing()
EndIf
EndProcedure
Procedure AddAndSortPolygon(newx, newy)
Protected i, distance.d
Protected x1, x2, y1, y2
Protected lowest = 0, current.d = 0
; add the new point to the polygon - set ID to -1 to check, where the new is
AddElement(polygons())
With polygons()
\id = 9999
\x = newx
\y = newy
EndWith
; get first point as a starter
ResetList(polygons())
NextElement(polygons())
x1 = polygons()\x
y1 = polygons()\y
For i = 0 To ListSize(polygons()) - 1
; get next point
SelectElement(polygons(), i)
x2 = polygons()\x
y2 = polygons()\y
; get distance
distance = Sqr((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))
; first element, get distance
If i = 1
current = distance
EndIf
; if distance is less than previous distances
If distance < current
current = distance
lowest = i
EndIf
Debug "from " + Str(i-1) + " to " + Str(i) + ": " + StrD(distance)
; get x1 and y1 to continue with checking
x1 = polygons()\x
y1 = polygons()\y
Next i
Debug "polygon should be inserted with id " + Str(lowest)
; set ID to +1 - do not change the ID 9999
For i = lowest To ListSize(polygons()) - 1
SelectElement(polygons(), i)
If polygons()\id <> 9999
polygons()\id = i + 1
EndIf
Next i
; search the one with ID -1
LastElement(polygons())
polygons()\id = lowest
; lastly sort by ID to get the correct rowing
SortStructuredList(polygons(), #PB_Sort_Ascending, OffsetOf(polygon_point_struct\id), TypeOf(polygon_point_struct\id))
ForEach polygons()
Debug polygons()\id
Next
EndProcedure
CreateImage(0, 500, 500, 32, #Black)
OpenWindow(0, 100, 100, 500, 500, "Test")
CanvasGadget(0, 0, 0, 500, 500)
SetGadgetAttribute(0, #PB_Canvas_Image, ImageID(0))
MakePolygons()
DrawPolygons()
Repeat
event = WaitWindowEvent(20)
If event = #PB_Event_CloseWindow
FreeImage(0)
FreeGadget(0)
CloseWindow(0)
End
EndIf
If event = #PB_Event_Gadget
If EventGadget() = 0 And EventType() = #PB_EventType_LeftClick
AddAndSortPolygon(375, 385) ; Great!
AddAndSortPolygon(99, 99) ; Great!
AddAndSortPolygon(99, 375) ; not great!
DrawPolygons()
EndIf
EndIf
ForEver
Re: Vector Drawing + one point
Posted: Mon Jan 29, 2024 12:44 pm
by Demivec
I have a question about how you choose where the point is added. In the pictures and example you laid out, you had five
five points in clockwise order around the edge of the polygon with the first point being p0(100,100). You added a new point and said that it should be added between points 2 & 3 instead of the incorrect choice of between points 0 and 1.
My question is why is the best choice between points 2 & 3 and not between points 3 & 4? The latter would be the two nearest points to the point being inserted. Are the two choices I listed considered equally good simply because neither choice causes a 'crossed line'?
After knowing the answer to these questions it would be simple to correct your code to select the proper insertion point.
Re: Vector Drawing + one point
Posted: Mon Jan 29, 2024 1:41 pm
by jamirokwai
Demivec wrote: Mon Jan 29, 2024 12:44 pm
I have a question about how you choose where the point is added. In the pictures and example you laid out, you had five
five points in clockwise order around the edge of the polygon with the first point being p0(100,100). You added a new point and said that it should be added between points 2 & 3 instead of the incorrect choice of between points 0 and 1.
My question is why is the best choice between points 2 & 3 and not between points 3 & 4? The latter would be the two nearest points to the point being inserted. Are the two choices I listed considered equally good simply because neither choice causes a 'crossed line'?
After knowing the answer to these questions it would be simple to correct your code to select the proper insertion point.
Hi demivec,
thanks for asking. Maybe, I should have put this event-loop in the first place. But I thought, there would be an all-in solution :-O
Here is a fresh event-loop to replace the original from above. I'd like to click anywhere in the canvas to have points added to the polygon without intersections. Left click: new point, right click: clear polygon and return to original.
Hope that makes it clearer?
Code: Select all
Repeat
event = WaitWindowEvent(20)
If event = #PB_Event_CloseWindow
FreeImage(0)
FreeGadget(0)
CloseWindow(0)
End
EndIf
If event = #PB_Event_Gadget
If EventGadget() = 0
Select EventType()
Case #PB_EventType_LeftClick
Define mx = GetGadgetAttribute(0, #PB_Canvas_MouseX)
Define my = GetGadgetAttribute(0, #PB_Canvas_MouseY)
AddAndSortPolygon(mx,my)
DrawPolygons()
Case #PB_EventType_RightClick
ClearList(polygons())
MakePolygons()
DrawPolygons()
EndSelect
EndIf
EndIf
ForEver
Re: Vector Drawing + one point
Posted: Mon Jan 29, 2024 3:50 pm
by ChrisR
Perhaps something like this to calculate distance to current element + distance to next element
Code: Select all
Procedure AddAndSortPolygon(newx, newy)
Protected lowestID = #PB_Default
Protected Distance.d, current.d = #PB_Default
Protected *polygons.polygon_point_struct
With polygons()
If ListSize(polygons()) > 2
ResetList(polygons())
While NextElement(polygons())
PushListPosition(polygons())
*polygons = NextElement(polygons())
If Not *polygons
*polygons = FirstElement(polygons())
EndIf
PopListPosition(polygons())
Distance = Sqr(Pow(newx-\x, 2) + Pow(newy-\y, 2)) + Sqr(Pow(newx-*polygons\x, 2) + Pow(newy-*polygons\y, 2))
If Distance < current Or current = #PB_Default
current = Distance
lowestID = \id
EndIf
Debug "ID = " + Str(\id) + " : Distance = " + StrD(Distance)
Wend
Debug "----------"
Debug "LowestID = " + Str(lowestID)
Debug "----------"
Else
lowestID = ListSize(polygons()) - 1
EndIf
If lowestID > -1
SelectElement(polygons(), lowestID)
EndIf
AddElement(polygons())
lowestID + 1
\id = lowestID
\x = newx
\y = newy
While NextElement(polygons())
lowestID + 1
\id = lowestID
Wend
EndWith
EndProcedure
Re: Vector Drawing + one point
Posted: Mon Jan 29, 2024 4:53 pm
by #NULL
I think there are situations where a new point would change other connections that are already there, not always just being inserted between two existing points. I would get the average coordinate of all points to get some kind of mid point. Then sort all other points by angle to the mid point.
Re: Vector Drawing + one point
Posted: Mon Jan 29, 2024 8:52 pm
by ChrisR
Yes, if we don't want an intersection, finding the midpoint and sorting by the angle of each point seems the right way to do it.
stackoverflow example her:
https://stackoverflow.com/a/19715160
Re: Vector Drawing + one point
Posted: Tue Jan 30, 2024 3:08 pm
by jamirokwai
Thanks for all your help. Here is my approach to the problem with angles, like ChrisR proposed. Sometimes, the lines will jump, usually at around 15 or more points. Not sure why, but I will investigate further.
The angle im my polygon_struct is for easy sorting
Code: Select all
EnableExplicit
Structure polygon_point_struct
id.w
x.w
y.w
angle.d
EndStructure
Global NewList polygons.polygon_point_struct()
Global event
Procedure DrawPolygons()
Protected start_x, start_y
SetGadgetAttribute(0, #PB_Canvas_Image, ImageID(0))
If StartVectorDrawing(CanvasVectorOutput(0))
ForEach polygons()
VectorSourceColor(RGBA(255,255,255,255))
ForEach polygons()
; draw lines between all the dots
With polygons()
; first dot? save x/y for later
If polygons()\id = 0
start_x = \x
start_y = \y
MovePathCursor(start_x, start_y)
EndIf
AddPathLine(\x, \y)
StrokePath(1)
; move to the end of the last line
MovePathCursor(\x, \y)
EndWith
Next
; am Ende noch die letzte Linie schließen
AddPathLine(start_x, start_y)
StrokePath(1)
Next
StopVectorDrawing()
EndIf
EndProcedure
Procedure AddAndSortPolygon(newx, newy)
Protected count = ListSize(polygons())
Protected i, lowestID
Protected center_x, center_y
; calculate the center: add all x and all y and divide by the count of points
ForEach polygons()
center_x + polygons()\x
center_y + polygons()\y
Next
center_x / count
center_y / count
; calculate all angles with atan2(point.y - center.y, point.x - center.x)
ForEach polygons()
With polygons()
\angle = ATan2(\x - center_x, \y - center_y)
EndWith
Next
; add the new point and calculate the angle between center And the new point
AddElement(polygons())
With polygons()
\id = count + 1
\angle = ATan2(newx- center_x, newy - center_y)
\x = newx
\y = newy
EndWith
; now sort by the angle, and change the IDs
SortStructuredList(polygons(), #PB_Sort_Ascending, OffsetOf(polygon_point_struct\angle), TypeOf(polygon_point_struct\angle))
; now set all IDs from 0 to size list to keep them sortable
i = 0
ForEach polygons()
polygons()\id = i
i + 1
Next
EndProcedure
CreateImage(0, 500, 500, 32, #Black)
OpenWindow(0, 100, 100, 500, 500, "Test")
CanvasGadget(0, 0, 0, 500, 500)
SetGadgetAttribute(0, #PB_Canvas_Image, ImageID(0))
DrawPolygons()
Repeat
event = WaitWindowEvent(20)
If event = #PB_Event_CloseWindow
FreeImage(0)
FreeGadget(0)
CloseWindow(0)
End
EndIf
If event = #PB_Event_Gadget
If EventGadget() = 0
Select EventType()
Case #PB_EventType_LeftClick
Define mx = GetGadgetAttribute(0, #PB_Canvas_MouseX)
Define my = GetGadgetAttribute(0, #PB_Canvas_MouseY)
AddAndSortPolygon(mx,my)
DrawPolygons()
Case #PB_EventType_RightClick
ClearList(polygons())
MakePolygons()
DrawPolygons()
EndSelect
EndIf
EndIf
ForEver
Re: Vector Drawing + one point
Posted: Wed Jan 31, 2024 4:08 pm
by ChrisR
I made a few changes:
Code: Select all
EnableExplicit
#DrawCenter = #True ; #True|#False
Structure polygon_point_struct
x.w
y.w
angle.d
distance.d
EndStructure
Global NewList polygons.polygon_point_struct()
Global event
Procedure DrawPolygons()
Protected start_x, start_y = -1
CompilerIf #DrawCenter
Protected center_x, center_y, count = ListSize(polygons())
CompilerEndIf
With polygons()
If StartVectorDrawing(CanvasVectorOutput(0))
VectorSourceColor(RGBA(0, 0, 0, 255))
FillVectorOutput()
If ListSize(polygons()) > 0
ForEach polygons()
CompilerIf #DrawCenter
center_x + polygons()\x
center_y + polygons()\y
CompilerEndIf
; If first initial point already done, draw lines
If start_y > -1
VectorSourceColor(RGBA(255, 255, 255, 255))
AddPathLine(\x, \y)
StrokePath(1)
Else
start_x = \x
start_y = \y
EndIf
; Move to first initial point or to the end of the last line
MovePathCursor(\x, \y)
Next
; Close the last line at the end if at least 3 points
If ListSize(polygons()) > 2
AddPathLine(start_x, start_y)
StrokePath(1)
CompilerIf #DrawCenter
VectorSourceColor(RGBA(255, 0, 0, 255))
AddPathCircle(center_x/count, center_y/count, 1)
StrokePath(2)
CompilerEndIf
EndIf
EndIf
StopVectorDrawing()
EndIf
EndWith
EndProcedure
Procedure AddAndSortPolygon(newx, newy)
Protected center_x, center_y, count
With polygons()
AddElement(polygons())
\x = newx
\y = newy
count = ListSize(polygons())
If count > 3
; calculate the center (average): add all x and all y and divide by the count of points
ForEach polygons()
center_x + polygons()\x
center_y + polygons()\y
Next
center_x / count
center_y / count
; calculate all angles with atan2(point.y - center.y, point.x - center.x) and the distance from the center
ForEach polygons()
\angle = ATan2(\x-center_x, \y-center_y)
\distance = Sqr(Pow(\x-center_x, 2) + Pow(\y-center_y, 2))
Next
; now sort by distance then by angle. Sort by distance first in case 3 or more points are on the same line
SortStructuredList(polygons(), #PB_Sort_Ascending, OffsetOf(polygon_point_struct\distance), TypeOf(polygon_point_struct\distance))
SortStructuredList(polygons(), #PB_Sort_Ascending, OffsetOf(polygon_point_struct\angle), TypeOf(polygon_point_struct\angle))
EndIf
EndWith
EndProcedure
OpenWindow(0, 100, 100, 500, 500, "Draw Polygons")
CanvasGadget(0, 0, 0, WindowWidth(0), WindowHeight(0))
DrawPolygons()
Repeat
event = WaitWindowEvent(20)
Select event
Case #PB_Event_CloseWindow
End
Case #PB_Event_Gadget
If EventGadget() = 0
Select EventType()
Case #PB_EventType_LeftClick
Define mx = GetGadgetAttribute(0, #PB_Canvas_MouseX)
Define my = GetGadgetAttribute(0, #PB_Canvas_MouseY)
AddAndSortPolygon(mx,my)
DrawPolygons()
Case #PB_EventType_RightClick
ClearList(polygons())
EndSelect
EndIf
EndSelect
ForEver
It works well but it's not always ideal, as can be seen here:
The bottom segments should keep the same form but they don't because the center moves

Re: Vector Drawing + one point
Posted: Thu Feb 01, 2024 1:21 pm
by ChrisR
The result with the center and angles, above, is not really optimal, I continued with Stargate's
idea here.
So by calculating the distances of the 2 segments that would be created, for each pair of points (point and next point).
Then, running the distances from smallest to largest, check whether one of the 2 future segments would intersect one of the other polygon segments.
If there is no intersection, we can add the point here.
Else, continue the loop and move on to the next smallest distance.
It looks much better, closer to what you'd do on a paper, with a pencil and eraser.
Code: Select all
;-Top
; -----------------------------------------------------------------------------
; Name: DrawPpolygon.pb
; Description: As its name suggests, draw a polygon, left-click to add a new point. Right click or F5 to reset and delete all points
; Author: ChrisR
; Date: 2024-01-02
; Version: 1.0
; PB-Version: Written under PB 6.04
; OS: Tested on Windows only
; Forum: https://www.purebasic.fr/english/viewtopic.php?t=83442
; -----------------------------------------------------------------------------
EnableExplicit
#DrawCenter = #True ; #True|#False
#Background_Color = $FF000000
#Line_Color = $FFFF0000
CompilerIf #DrawCenter
#Center_Color = $FF0000FF
CompilerEndIf
#Epsilon = 0.000001
#Shortcut_Escape = 3
#Shortcut_F5 = 5
Structure PointD
x.d
y.d
EndStructure
Structure polygon_point_struct
id.w
point1.PointD
point2.PointD
distance.d
EndStructure
Global NewList polygons.polygon_point_struct()
Procedure IntersectSegments (*p1.PointD, *p2.PointD, *p3.PointD, *p4.PointD) ; to send the crossover point back, if needed: *ps1.PointD)
; Based on Little John's Intersection of two line segments [http://www.purebasic.fr/english/viewtopic.php?f=12&t=53070]
; -- Reduced here as it is only for the intersection of 2 segments, without external points
Protected.d numera, numerb, denom, mua, mub
numera = (*p4\x-*p3\x)*(*p1\y-*p3\y) - (*p4\y-*p3\y)*(*p1\x-*p3\x)
numerb = (*p2\x-*p1\x)*(*p1\y-*p3\y) - (*p2\y-*p1\y)*(*p1\x-*p3\x)
denom = (*p4\y-*p3\y)*(*p2\x-*p1\x) - (*p4\x-*p3\x)*(*p2\y-*p1\y)
If Abs(denom) >= #Epsilon ; if the lines are not parallel
mua = numera / denom
mub = numerb / denom
If mua > 0.0 And mua < 1.0 And mub > 0.0 And mub < 1.0 ; if the intersection is inside the segments, without external points
; *ps1\x = *p1\x + mua * (*p2\x-*p1\x) : *ps1\y = *p1\y + mua * (*p2\y-*p1\y)
ProcedureReturn #True
EndIf
EndIf
EndProcedure
Procedure LoopIntersectSegments(id, *point1.PointD, *point2.PointD)
Protected Intersect
With polygons()
PushListPosition(polygons())
ForEach polygons()
If Not \id = id
If IntersectSegments(*point1, *point2, \point1, \point2)
Intersect = #True
Break
EndIf
EndIf
Next
PopListPosition(polygons())
EndWith
ProcedureReturn Intersect
EndProcedure
Procedure DrawPolygons()
Protected StartPoint.PointD
CompilerIf #DrawCenter
Protected CenterPoint.PointD, count = ListSize(polygons())
CompilerEndIf
StartPoint\x = -1
With polygons()
If StartVectorDrawing(CanvasVectorOutput(0))
VectorSourceColor(#Background_Color)
FillVectorOutput()
If ListSize(polygons()) > 0
ForEach polygons()
CompilerIf #DrawCenter
CenterPoint\x + \point1\x : CenterPoint\y + \point1\y
CompilerEndIf
; If first point done (MovePathCursor), then draw lines
If StartPoint\x > -1
VectorSourceColor(#Line_Color)
AddPathLine(\point1\x, \point1\y)
StrokePath(1)
Else
StartPoint\x = \point1\x : StartPoint\y = \point1\y
EndIf
; move to first point or to the end of the last line
MovePathCursor(\point1\x, \point1\y)
Next
; Close the last line at the end if at least 3 points
If ListSize(polygons()) > 2
AddPathLine(StartPoint\x, StartPoint\y)
StrokePath(1)
CompilerIf #DrawCenter
VectorSourceColor(#Center_Color)
AddPathCircle(CenterPoint\x / count, CenterPoint\y / count, 1)
StrokePath(2)
CompilerEndIf
EndIf
EndIf
StopVectorDrawing()
EndIf
EndWith
EndProcedure
Procedure AddAndSortPolygon(*NewPoint.PointD)
Protected lowestID = #PB_Default
Protected *polygons.polygon_point_struct
With polygons()
If ListSize(polygons()) > 2
ForEach polygons()
PushListPosition(polygons())
*polygons = NextElement(polygons())
If Not *polygons
*polygons = FirstElement(polygons())
EndIf
PopListPosition(polygons())
\point2\x = *polygons\point1\x
\point2\y = *polygons\point1\y
\distance = Sqr(Pow(*NewPoint\x-\point1\x, 2) + Pow(*NewPoint\y-\point1\y, 2)) + Sqr(Pow(*NewPoint\x-\point2\x, 2) + Pow(*NewPoint\y-\point2\y, 2))
Debug "ID = " + Str(\id) + " : PointXY: " + Str(\point1\x) + " | " + Str(\point1\y) + " : Distance = " + StrD(\distance)
Next
; sort by distance
SortStructuredList(polygons(), #PB_Sort_Ascending, OffsetOf(polygon_point_struct\distance), TypeOf(polygon_point_struct\distance))
Debug "----------"
ForEach polygons()
;Check If one of the 2 future segments created (replacing the previous one) does not cross one of the other polygon segments
;Else continue and move on to the next smallest distance
If LoopIntersectSegments(\id, \point1, *NewPoint)
Debug "Point ID = " + Str(\id) + " has an intersection on 1st segment"
Else
If LoopIntersectSegments(\id, \point2, *NewPoint)
Debug "Point ID = " + Str(\id) + " has an intersection on 2nd segment"
Else
lowestID = \id
Debug "Lowest Point ID used = " + Str(lowestID)
Break
EndIf
EndIf
Next
Debug "----------"
; Re sort by id to insert the point element in the right place
SortStructuredList(polygons(), #PB_Sort_Ascending, OffsetOf(polygon_point_struct\id), TypeOf(polygon_point_struct\id))
Else
lowestID = ListSize(polygons()) - 1
EndIf
If lowestID > -1
SelectElement(polygons(), lowestID)
EndIf
AddElement(polygons())
lowestID + 1
\id = lowestID
\point1\x = *NewPoint\x
\point1\y = *NewPoint\y
While NextElement(polygons())
lowestID + 1
\id = lowestID
Wend
EndWith
EndProcedure
;- Main
Define NewPoint.PointD
Define event
OpenWindow(0, 100, 100, 500, 500, "Test")
CanvasGadget(0, 0, 0, WindowWidth(0), WindowHeight(0))
AddKeyboardShortcut(0, #PB_Shortcut_Escape, #Shortcut_Escape)
AddKeyboardShortcut(0, #PB_Shortcut_F5, #Shortcut_F5)
DrawPolygons()
Repeat
Select WaitWindowEvent(10)
Case #PB_Event_CloseWindow
End
Case #PB_Event_Menu
Select EventMenu()
Case #Shortcut_Escape
End
Case #Shortcut_F5
PostEvent(#PB_Event_Gadget, 0, 0, #PB_EventType_RightClick)
EndSelect
Case #PB_Event_Gadget
If EventGadget() = 0
Select EventType()
Case #PB_EventType_LeftClick
NewPoint\x = GetGadgetAttribute(0, #PB_Canvas_MouseX)
NewPoint\y = GetGadgetAttribute(0, #PB_Canvas_MouseY)
AddAndSortPolygon(NewPoint)
DrawPolygons()
Case #PB_EventType_RightClick
ClearList(polygons())
DrawPolygons()
EndSelect
EndIf
EndSelect
ForEver
Re: Vector Drawing + one point
Posted: Thu Feb 01, 2024 1:49 pm
by jamirokwai
ChrisR wrote: Thu Feb 01, 2024 1:21 pm
The result with the center and angles, above, is not really optimal, I continued with Stargate's
idea here.
Wow, ChrisR. Thanks a lot, that looks and works much better!