Middlepoint on a curve created by AddPathCurve
Re: Middlepoint on a curve created by AddPathCurve
The easiest way I think is to do a close approximation of the curve with small line segments.
Count the length of all segments together, find out on which segment the midpoint is located and interpolate on that segment to find the interpolated location.
The endpoints of the segment on which the midpoint is located can be used to calculate the angle of the segment.
Count the length of all segments together, find out on which segment the midpoint is located and interpolate on that segment to find the interpolated location.
The endpoints of the segment on which the midpoint is located can be used to calculate the angle of the segment.
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: Middlepoint on a curve created by AddPathCurve
This one? https://www.microsoft.com/en-us/downloa ... x?id=34429DK_PETER wrote:1. Could you try to reinstall DirectX 9c drivers and try again? You need them in Windows 10 too.
Example works properly with OGL in both x86 and x64 version, yes!2. See if you can run it using OpenGL in subsystem.
- Didelphodon
- PureBasic Expert
- Posts: 450
- Joined: Sat Dec 18, 2004 11:56 am
- Location: Vienna - Austria
- Contact:
Re: Middlepoint on a curve created by AddPathCurve
Sounds reasonable. You don't have a code example, do you? ;-Pwilbert wrote:The easiest way I think is to do a close approximation of the curve with small line segments.
Count the length of all segments together, find out on which segment the midpoint is located and interpolate on that segment to find the interpolated location.
The endpoints of the segment on which the midpoint is located can be used to calculate the angle of the segment.
Go, tell it on the mountains.
Re: Middlepoint on a curve created by AddPathCurve
No PureBasic code.Didelphodon wrote:You don't have a code example, do you? ;-P
Years ago I did this one with ActionScript.
It uses the same approach to animate along a path in a linear speed.
Last edited by wilbert on Wed May 31, 2017 3:06 pm, edited 1 time in total.
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
-
- Addict
- Posts: 4778
- Joined: Thu Jun 07, 2007 3:25 pm
- Location: Berlin, Germany
Re: Middlepoint on a curve created by AddPathCurve
That's a good idea.wilbert wrote:The easiest way I think is to do a close approximation of the curve with small line segments.
Count the length of all segments together, find out on which segment the midpoint is located and interpolate on that segment to find the interpolated location.

Below there is some code that does do so.
@Didelphodon:wilbert wrote:The endpoints of the segment on which the midpoint is located can be used to calculate the angle of the segment.
I am too lazy now to calculate that angle, but I added a Debug message that contains a hint.

Code: Select all
; tested with PB 5.42 beta 2 x64 on Windows 10
EnableExplicit
Structure PointD
x.d
y.d
EndStructure
Procedure DeCasteljau (x0.d, y0.d, x1.d, y1.d, x2.d, y2.d, x3.d, y3.d, t.d, *p.PointD)
; -- De Casteljau's algorithm
; <http://stackoverflow.com/questions/14174252/how-to-find-out-y-coordinate-of-specific-point-in-bezier-curve-in-canvas>, 2016-02-22
; in : x0, y0, x1, y1, x2, y2, x3, y3: see PB's AddPathCurve()
; (x0, y0 = current position of the cursor)
; t: rational number from the interval [0.0; 1.0]
; out: *p: Coordinates of the wanted point
Protected.d Ax, Ay, Bx, By, Cx, Cy, Dx, Dy, Ex, Ey
Ax = (1.0 - t) * x0 + t * x1
Ay = (1.0 - t) * y0 + t * y1
Bx = (1.0 - t) * x1 + t * x2
By = (1.0 - t) * y1 + t * y2
Cx = (1.0 - t) * x2 + t * x3
Cy = (1.0 - t) * y2 + t * y3
Dx = (1.0 - t) * Ax + t * Bx
Dy = (1.0 - t) * Ay + t * By
Ex = (1.0 - t) * Bx + t * Cx
Ey = (1.0 - t) * By + t * Cy
*p\x = (1.0 - t) * Dx + t * Ex
*p\y = (1.0 - t) * Dy + t * Ey
EndProcedure
Procedure.d Distance (*p0.PointD, *p1.PointD)
; in : Coordinates of two points
; out: Distance between both points
Protected.d dx, dy
dx = *p1\x - *p0\x
dy = *p1\y - *p0\y
ProcedureReturn Sqr(dx*dx + dy*dy)
EndProcedure
Procedure MidPoint (x0.d, y0.d, x1.d, y1.d, x2.d, y2.d, x3.d, y3.d, n.i, *m.PointD)
; in : x0, y0, x1, y1, x2, y2, x3, y3: see PB's AddPathCurve()
; (x0, y0 = current position of the cursor)
; n: number of line segments for approximation
; (the higher this number, the more precise will be the result)
; out: *m: Coordinates of the midpoint of the curve
Protected i.i, t.d, t0.d, t1.d, halfLen.d=0.0, temp.d=0.0
Protected p0.PointD, p1.PointD
; get approximately half the length of the curve
DeCasteljau(x0, y0, x1, y1, x2, y2, x3, y3, 0.0, @p0)
For i = 1 To n
t = i / n
DeCasteljau(x0, y0, x1, y1, x2, y2, x3, y3, t, @p1)
halfLen + Distance(@p0, @p1)
CopyStructure(@p1, @p0, PointD)
Next
halfLen / 2.0
; get the segment where the midpoint of the length of the curve is located
DeCasteljau(x0, y0, x1, y1, x2, y2, x3, y3, 0.0, @p0)
For i = 1 To n
t = i / n
DeCasteljau(x0, y0, x1, y1, x2, y2, x3, y3, t, @p1)
temp + Distance(@p0, @p1)
If temp > halfLen
t0 = (i - 1) / n
t1 = t
Break
EndIf
CopyStructure(@p1, @p0, PointD)
Next
; calculate approximately the coordinates of the midpoint
*m\x = p0\x + (p1\x - p0\x) / 2
*m\y = p0\y + (p1\y - p0\y) / 2
Debug "The midpoint is between t0 = " + StrD(t0, 2) + " and t1 = " + StrD(t1, 2) + "."
Debug "It is approximately located at Mx = " + StrD(*m\x, 2) + ", My = " + StrD(*m\y, 2) + "."
Debug "(Use p0 and p1 together with Atan2() to get the angle of the segment that contains the midpoint.)"
EndProcedure
; -- Demo
Define.d x0, y0, x1, y1, x2, y2, x3, y3
Define.i i
Define p.PointD
x0 = 50 : y0 = 100
x1 = 90 : y1 = 30
x2 = 250 : y2 = 180
x3 = 350 : y3 = 100
OpenWindow(0, 0, 0, 400, 200, "Midpoint of bezier curve", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, 400, 200)
; AddPathCurve(): red line
If StartVectorDrawing(CanvasVectorOutput(0))
MovePathCursor(x0, y0)
AddPathCurve(x1, y1, x2, y2, x3, y3)
VectorSourceColor(RGBA(255, 0, 0, 255))
StrokePath(10)
StopVectorDrawing()
EndIf
; DeCasteljau() for t = 0.5: blue circle
DeCasteljau(x0, y0, x1, y1, x2, y2, x3, y3, 0.5, @p)
If StartVectorDrawing(CanvasVectorOutput(0))
AddPathCircle(p\x, p\y, 5)
VectorSourceColor(RGBA(0, 0, 255, 255))
StrokePath(2)
StopVectorDrawing()
EndIf
; Midpoint of the curve: green circle
MidPoint(x0, y0, x1, y1, x2, y2, x3, y3, 10, @p)
If StartVectorDrawing(CanvasVectorOutput(0))
AddPathCircle(p\x, p\y, 5)
VectorSourceColor(RGBA(0, 255, 0, 255))
StrokePath(2)
StopVectorDrawing()
EndIf
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow

Last edited by Little John on Mon Feb 22, 2016 11:12 pm, edited 1 time in total.
- Didelphodon
- PureBasic Expert
- Posts: 450
- Joined: Sat Dec 18, 2004 11:56 am
- Location: Vienna - Austria
- Contact:
Re: Middlepoint on a curve created by AddPathCurve
@All: Thx for all your efforts
Go, tell it on the mountains.
Re: Middlepoint on a curve created by AddPathCurve
Nice one Little John. I think that shows quite nicely that putting t=1/2 does not, in all but the simplest cases, give the proper mid-point of the bezier.
I may look like a mule, but I'm not a complete ass.
Re: Middlepoint on a curve created by AddPathCurve
For approximation 0.00001 (Near perfect)
Code: Select all
Global length.f, i.f
Global Dim XY.f(1)
Procedure.f BezierMidPoint(x1,y1,x2,y2,x3,y3,x4,y4,approx.f)
xx=x1
yy=y1
cx.f=3*(x2-x1)
bx.f=3*(x3-x2)-cx
ax.f=x4-x1-cx-bx
cy.f=3*(y2-y1)
by.f=3*(y3-y2)-cy
ay.f=y4-y1-cy-by
length = 0.0
Repeat
i+approx
x=((ax*i+bx)*i+cx)*i+x1
y=((ay*i+by)*i+cy)*i+y1
If i>0
length = length + Sqr(Pow(x-xx, 2) + Pow(y-yy, 2))
EndIf
xx=x
yy=y
Until i > 1
llength.f = length
xx=x1
yy=y1
length = 0.0
i.f = 0.0
Repeat
i+approx
x=((ax*i+bx)*i+cx)*i+x1
y=((ay*i+by)*i+cy)*i+y1
If i>0
length = length + Sqr(Pow(x-xx, 2) + Pow(y-yy, 2))
If length > llength/2
xy(0) = x
xy(1) = y
Break
EndIf
EndIf
xx=x
yy=y
Until i > 1
EndProcedure
BezierMidPoint(50,100,90,30,250,180,350,100,0.00001)
Debug xy(0)
Debug xy(1)
OpenWindow(0, 0, 0, 400, 200, "Midpoint of bezier curve", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, 400, 200)
If StartVectorDrawing(CanvasVectorOutput(0))
MovePathCursor(50,100)
AddPathCurve(90,30,250,180,350,100)
VectorSourceColor($FF0005EB)
StrokePath(10)
ResetPath()
VectorSourceColor($FF14EB00)
AddPathCircle(xy(0),xy(1),5)
StrokePath(2)
StopVectorDrawing()
EndIf
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Egypt my love
Re: Middlepoint on a curve created by AddPathCurve
Nice workLittle John wrote:That's a good idea.
Below there is some code that does do so.

What I like about De Casteljau's algorithm is that at places where the curve changes a lot the calculated points are closer together and where the curve doesn't change that much they are further apart.
As a result of this you don't need thousands of points to get a rather good approximation as you did demonstrate with your example which does a pretty good job with only 10 line segments.
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
- Didelphodon
- PureBasic Expert
- Posts: 450
- Joined: Sat Dec 18, 2004 11:56 am
- Location: Vienna - Austria
- Contact:
Middlepoint on a curve created by AddPathCurve
@RASHAD, Little John: How would your approach apply to a curve/path consisting of more points? As I mentioned, my curves can have an undefined number of points.
Go, tell it on the mountains.
Re: Middlepoint on a curve created by AddPathCurve
Hi Didelphodon
- The Blue Boxes are your nodes
- Pick one node before each two Control nodes and another after etch two(The Black circles)
- The Green Circles are the mid points of each segment
This is the way I use to do such things
Here I used approximation 0.005 for speed but it is still sufficient
- The Blue Boxes are your nodes
- Pick one node before each two Control nodes and another after etch two(The Black circles)
- The Green Circles are the mid points of each segment
This is the way I use to do such things
Here I used approximation 0.005 for speed but it is still sufficient
Code: Select all
Global length.f, i.f
Global Dim XY.f(1)
Procedure.f BezierMidPoint(x1,y1,x2,y2,x3,y3,x4,y4,approx.f)
xx=x1
yy=y1
cx.f=3*(x2-x1)
bx.f=3*(x3-x2)-cx
ax.f=x4-x1-cx-bx
cy.f=3*(y2-y1)
by.f=3*(y3-y2)-cy
ay.f=y4-y1-cy-by
length = 0.0
Repeat
i+approx
x=((ax*i+bx)*i+cx)*i+x1
y=((ay*i+by)*i+cy)*i+y1
If i>0
length = length + Sqr(Pow(x-xx, 2) + Pow(y-yy, 2))
EndIf
xx=x
yy=y
Until i > 1
llength.f = length
xx=x1
yy=y1
length = 0.0
i.f = 0.0
Repeat
i+approx
x=((ax*i+bx)*i+cx)*i+x1
y=((ay*i+by)*i+cy)*i+y1
If i>0
length = length + Sqr(Pow(x-xx, 2) + Pow(y-yy, 2))
If length > llength/2
xy(0) = x
xy(1) = y
Break
EndIf
EndIf
xx=x
yy=y
Until i > 1
EndProcedure
BezierMidPoint(50,100,90,30,250,180,350,100,0.005)
centx1.f = xy(0)
centy1.f = xy(1)
BezierMidPoint(350,100,400, 60, 450, 290, 550, 200,0.005)
centx2.f = xy(0)
centy2.f = xy(1)
If OpenWindow(0, 0, 0, 600, 350, "VectorDrawing", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, 600, 350)
If StartVectorDrawing(CanvasVectorOutput(0))
MovePathCursor(50, 100)
AddPathCurve(90, 30, 250, 180, 350, 100)
VectorSourceColor($FF0003F1)
StrokePath(10)
ResetPath()
VectorSourceColor($FF14EB00)
AddPathCircle(centx1,centy1,5)
StrokePath(2)
VectorSourceColor($FF0003F1)
MovePathCursor(350, 100)
AddPathCurve(400, 60, 450, 290, 550, 200)
StrokePath(10)
ResetPath()
VectorSourceColor($FF14EB00)
AddPathCircle(centx2,centy2,5)
StrokePath(2)
ResetPath()
VectorSourceColor($FF000000)
AddPathCircle(50,100,5)
AddPathCircle(350,100,5)
AddPathCircle(550,200,5)
FillPath()
ResetPath()
VectorSourceColor($FFF11700)
AddPathBox(90,30,10,10)
AddPathBox(250,180,10,10)
AddPathBox(400,60,10,10)
AddPathBox(450,290,10,10)
FillPath()
StopVectorDrawing()
EndIf
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf
Egypt my love
-
- Addict
- Posts: 4778
- Joined: Thu Jun 07, 2007 3:25 pm
- Location: Berlin, Germany
Re: Middlepoint on a curve created by AddPathCurve
How do you use PB's AddPathCurve() for such a curve with multiple points? Can you post a working code example?Didelphodon wrote:@RASHAD, Little John: How would your approach apply to a curve/path consisting of more points? As I mentioned, my curves can have an undefined number of points.
- Didelphodon
- PureBasic Expert
- Posts: 450
- Joined: Sat Dec 18, 2004 11:56 am
- Location: Vienna - Austria
- Contact:
Re: Middlepoint on a curve created by AddPathCurve
At least with the txt-output of Graphviz the included Bezier curves can be drawn perfectly equal with the following code ...Little John wrote:How do you use PB's AddPathCurve() for such a curve with multiple points? Can you post a working code example?Didelphodon wrote:@RASHAD, Little John: How would your approach apply to a curve/path consisting of more points? As I mentioned, my curves can have an undefined number of points.
Code: Select all
Procedure AddPathBezierCurve(List Points.struct_Point(), xDisplacement.d = 0, yDisplacement.d = 0)
ForEach Points()
If (Not ListIndex(Points()))
MovePathCursor(xDisplacement + Points()\x, yDisplacement + Points()\y)
Else
Select (ListSize(Points()) - ListIndex(Points()))
Case 1
x1.i = xDisplacement + Points()\x
y1.i = yDisplacement + Points()\y
x2.i = xDisplacement + Points()\x
y2.i = yDisplacement + Points()\y
x3.i = xDisplacement + Points()\x
y3.i = yDisplacement + Points()\y
AddPathCurve(x1, y1, x2, y2, x3, y3)
; AddPathLine(x1, y1)
Case 2
x1.i = xDisplacement + Points()\x
y1.i = yDisplacement + Points()\y
NextElement(Points())
x2.i = xDisplacement + Points()\x
y2.i = yDisplacement + Points()\y
x3.i = xDisplacement + Points()\x
y3.i = yDisplacement + Points()\y
AddPathCurve(x1, y1, x2, y2, x3, y3)
Default
x1.i = xDisplacement + Points()\x
y1.i = yDisplacement + Points()\y
NextElement(Points())
x2.i = xDisplacement + Points()\x
y2.i = yDisplacement + Points()\y
NextElement(Points())
x3.i = xDisplacement + Points()\x
y3.i = yDisplacement + Points()\y
AddPathCurve(x1, y1, x2, y2, x3, y3)
EndSelect
EndIf
Next
EndProcedure
Go, tell it on the mountains.
- Didelphodon
- PureBasic Expert
- Posts: 450
- Joined: Sat Dec 18, 2004 11:56 am
- Location: Vienna - Austria
- Contact:
Re: Middlepoint on a curve created by AddPathCurve
Thx again for all of your contributions! Based on various code-examples in this thread I was able to hack together something that covers all the features I initially needed.
Here's the code I'm currently using ...
And here is an image that takes advantage of this code - it's entirely drawn using the vector drawing library ...

Absolutely perfect would be to have the text following the curve but I can already live quite comfortably with the current solution thx to you guys.
Here's the code I'm currently using ...
Code: Select all
CompilerIf Not Defined(struct_Point, #PB_Structure)
Structure struct_Point
x.d
y.d
EndStructure
CompilerEndIf
Procedure DeCasteljau (x0.d, y0.d, x1.d, y1.d, x2.d, y2.d, x3.d, y3.d, t.d, *p.struct_Point)
; -- De Casteljau's algorithm
; <http://stackoverflow.com/questions/14174252/how-to-find-out-y-coordinate-of-specific-point-in-bezier-curve-in-canvas>, 2016-02-22
; in : x0, y0, x1, y1, x2, y2, x3, y3: see PB's AddPathCurve()
; (x0, y0 = current position of the cursor)
; t: rational number from the interval [0.0; 1.0]
; out: *p: Coordinates of the wanted point
Protected.d Ax, Ay, Bx, By, Cx, Cy, Dx, Dy, Ex, Ey
Ax = (1.0 - t) * x0 + t * x1
Ay = (1.0 - t) * y0 + t * y1
Bx = (1.0 - t) * x1 + t * x2
By = (1.0 - t) * y1 + t * y2
Cx = (1.0 - t) * x2 + t * x3
Cy = (1.0 - t) * y2 + t * y3
Dx = (1.0 - t) * Ax + t * Bx
Dy = (1.0 - t) * Ay + t * By
Ex = (1.0 - t) * Bx + t * Cx
Ey = (1.0 - t) * By + t * Cy
*p\x = (1.0 - t) * Dx + t * Ex
*p\y = (1.0 - t) * Dy + t * Ey
EndProcedure
Procedure.d Distance (*p0.struct_Point, *p1.struct_Point)
; in : Coordinates of two points
; out: Distance between both points
Protected.d dx, dy
dx = *p1\x - *p0\x
dy = *p1\y - *p0\y
ProcedureReturn Sqr(dx*dx + dy*dy)
EndProcedure
Procedure AddPathBezierCurve(List Points.struct_Point(), xDisplacement.d = 0, yDisplacement.d = 0)
ForEach Points()
If (Not ListIndex(Points()))
MovePathCursor(xDisplacement + Points()\x, yDisplacement + Points()\y)
Else
Select (ListSize(Points()) - ListIndex(Points()))
Case 1
x1.i = xDisplacement + Points()\x
y1.i = yDisplacement + Points()\y
x2.i = xDisplacement + Points()\x
y2.i = yDisplacement + Points()\y
x3.i = xDisplacement + Points()\x
y3.i = yDisplacement + Points()\y
AddPathCurve(x1, y1, x2, y2, x3, y3)
; AddPathLine(x1, y1)
Case 2
x1.i = xDisplacement + Points()\x
y1.i = yDisplacement + Points()\y
NextElement(Points())
x2.i = xDisplacement + Points()\x
y2.i = yDisplacement + Points()\y
x3.i = xDisplacement + Points()\x
y3.i = yDisplacement + Points()\y
AddPathCurve(x1, y1, x2, y2, x3, y3)
Default
x1.i = xDisplacement + Points()\x
y1.i = yDisplacement + Points()\y
NextElement(Points())
x2.i = xDisplacement + Points()\x
y2.i = yDisplacement + Points()\y
NextElement(Points())
x3.i = xDisplacement + Points()\x
y3.i = yDisplacement + Points()\y
AddPathCurve(x1, y1, x2, y2, x3, y3)
EndSelect
EndIf
Next
EndProcedure
Global _gl_GetBezierCurveMiddleAngleP0.struct_Point
Global _gl_GetBezierCurveMiddleAngleP1.struct_Point
Procedure.d GetBezierCurveMiddleAngle()
ProcedureReturn Degree(ATan2(_gl_GetBezierCurveMiddleAngleP1\x - _gl_GetBezierCurveMiddleAngleP0\x, _gl_GetBezierCurveMiddleAngleP1\y - _gl_GetBezierCurveMiddleAngleP0\y))
EndProcedure
Procedure GetBezierCurveMiddle(*Middle.struct_Point, List Points.struct_Point(), lineSegmentsForApproximation.i = 10, xDisplacement.d = 0, yDisplacement.d = 0)
length.d = 0
ForEach Points()
If (Not ListIndex(Points()))
x0.d = xDisplacement + Points()\x
y0.d = yDisplacement + Points()\y
Else
Select (ListSize(Points()) - ListIndex(Points()))
Case 1
x1.d = xDisplacement + Points()\x
y1.d = yDisplacement + Points()\y
x2.d = xDisplacement + Points()\x
y2.d = yDisplacement + Points()\y
x3.d = xDisplacement + Points()\x
y3.d = yDisplacement + Points()\y
Case 2
x1.d = xDisplacement + Points()\x
y1.d = yDisplacement + Points()\y
NextElement(Points())
x2.d = xDisplacement + Points()\x
y2.d = yDisplacement + Points()\y
x3.d = xDisplacement + Points()\x
y3.d = yDisplacement + Points()\y
Default
x1.d = xDisplacement + Points()\x
y1.d = yDisplacement + Points()\y
NextElement(Points())
x2.d = xDisplacement + Points()\x
y2.d = yDisplacement + Points()\y
NextElement(Points())
x3.d = xDisplacement + Points()\x
y3.d = yDisplacement + Points()\y
EndSelect
DeCasteljau(x0, y0, x1, y1, x2, y2, x3, y3, 0.0, @p0.struct_Point)
For i.i = 1 To lineSegmentsForApproximation
t.d = i / lineSegmentsForApproximation
DeCasteljau(x0, y0, x1, y1, x2, y2, x3, y3, t, @p1.struct_Point)
length + Distance(@p0, @p1)
CopyStructure(@p1, @p0, struct_Point)
Next i
x0 = x3
y0 = y3
EndIf
Next
length2.d = length / 2
hlength.d = 0
ForEach Points()
If (Not ListIndex(Points()))
x0.d = xDisplacement + Points()\x
y0.d = yDisplacement + Points()\y
Else
Select (ListSize(Points()) - ListIndex(Points()))
Case 1
x1.d = xDisplacement + Points()\x
y1.d = yDisplacement + Points()\y
x2.d = xDisplacement + Points()\x
y2.d = yDisplacement + Points()\y
x3.d = xDisplacement + Points()\x
y3.d = yDisplacement + Points()\y
Case 2
x1.d = xDisplacement + Points()\x
y1.d = yDisplacement + Points()\y
NextElement(Points())
x2.d = xDisplacement + Points()\x
y2.d = yDisplacement + Points()\y
x3.d = xDisplacement + Points()\x
y3.d = yDisplacement + Points()\y
Default
x1.d = xDisplacement + Points()\x
y1.d = yDisplacement + Points()\y
NextElement(Points())
x2.d = xDisplacement + Points()\x
y2.d = yDisplacement + Points()\y
NextElement(Points())
x3.d = xDisplacement + Points()\x
y3.d = yDisplacement + Points()\y
EndSelect
DeCasteljau(x0, y0, x1, y1, x2, y2, x3, y3, 0.0, @p0.struct_Point)
For i.i = 1 To lineSegmentsForApproximation
t.d = i / lineSegmentsForApproximation
DeCasteljau(x0, y0, x1, y1, x2, y2, x3, y3, t, @p1.struct_Point)
hlength + Distance(@p0, @p1)
If hlength > length2
t0.d = (i - 1) / lineSegmentsForApproximation
t1.d = t
Break 2
EndIf
CopyStructure(@p1, @p0, struct_Point)
Next i
x0 = x3
y0 = y3
EndIf
Next
*Middle\x = p0\x + (p1\x - p0\x) / 2
*Middle\y = p0\y + (p1\y - p0\y) / 2
CopyStructure(p0, _gl_GetBezierCurveMiddleAngleP0, struct_Point)
CopyStructure(p1, _gl_GetBezierCurveMiddleAngleP1, struct_Point)
EndProcedure

Absolutely perfect would be to have the text following the curve but I can already live quite comfortably with the current solution thx to you guys.

Go, tell it on the mountains.
-
- Addict
- Posts: 4778
- Joined: Thu Jun 07, 2007 3:25 pm
- Location: Berlin, Germany
Re: Middlepoint on a curve created by AddPathCurve
Oops, I'm too slow.
While I was writing an answer, you posted again ...
Well, here is my reply, I hope that it's understandable.
Your image looks impressive. 

Well, here is my reply, I hope that it's understandable.
Code: Select all
Procedure AddPathBezierCurve(List Points.struct_Point(), xDisplacement.d = 0, yDisplacement.d = 0)
Protected halfLen.d=0.0, temp.d=0.0
ForEach Points()
If (Not ListIndex(Points()))
MovePathCursor(xDisplacement + Points()\x, yDisplacement + Points()\y)
Else
Select (ListSize(Points()) - ListIndex(Points()))
Case 1
[...]
AddPathCurve(x1, y1, x2, y2, x3, y3)
halfLen + <length of this Bezier segment As shown before>
Case 2
[...]
AddPathCurve(x1, y1, x2, y2, x3, y3)
halfLen + <length of this Bezier segment As shown before>
Default
[...]
AddPathCurve(x1, y1, x2, y2, x3, y3)
halfLen + <length of this Bezier segment As shown before>
EndSelect
EndIf
Next
halfLen / 2
ForEach Points()
If (Not ListIndex(Points()))
; MovePathCursor(xDisplacement + Points()\x, yDisplacement + Points()\y)
Else
Select (ListSize(Points()) - ListIndex(Points()))
Case 1
[...]
temp + <length of this Bezier segment As shown before>
If temp > halfLen
Break
EndIf
Case 2
[...]
temp + <length of this Bezier segment As shown before>
If temp > halfLen
Break
EndIf
Default
[...]
temp + <length of this Bezier segment As shown before>
If temp > halfLen
Break
EndIf
EndSelect
EndIf
Next
excess = temp - halfLen
; The Break took place in the Bezier segment where the midpoint of the whole curve is.
; Now investigate that segment similar as shown before. However, now don't look for
; the midpoint of that segment, but for <length of that segment> - excess.
EndProcedure

You might want to look at Danilo's DrawBezierText().Absolutely perfect would be to have the text following the curve [...]