Bezier Curves, algorithm of de Casteljau
Sunday, November 1st, 2009I started reading on Curve models and geometries, different types of Spline algorithms. This is a first attempt to generate Bezier curvers using the algorithm of de Casteljau. The script uses a selected polyline as the control polygon of the curve. The Bezier is created in several steps to illustrate the process. It runs under Microstation MVBA.
‘Linestring Bezier Approximation after Casteljau’s algorithm
‘Sebastian Gmelin
’24.10.2009
‘draw and select linestring and run script
Const cDiv As Long = 5 ‘subdivision at which guidlines are drawn and a copy of the drawing set is created
Const div As Long = 50 ‘subdivision between cDiv for bezier spline points (total subdivision = cDiv * div)
Dim cPoints() As Point3d
Dim bPoints() As Point3d
Dim cSize As Point3d
Dim cLine As Element
Private Sub ScanDesignFile()
‘scan active designfile for selected linestrings
Dim oElEnum As ElementEnumerator
Dim oElem As Element
‘get collection of selected elements
Set oElEnum = ActiveModelReference.GetSelectedElements
ActiveModelReference.UnselectAllElements
‘go through selection set
While oElEnum.MoveNext
Set oElem = oElEnum.Current
‘check if active element is linestring
If (oElem.IsVertexList) Then
Debug.Print (“Linestring”)
cPoints = oElem.AsVertexList.GetVertices ‘save collection of vertices
Set cLine = oElem
End If
Wend
End Sub
Private Sub getSize()
‘get linestring size for element copies offset
Dim i As Long
Dim min As Point3d
Dim max As Point3d
Dim lineString As Element
min = Point3dFromXYZ(1E+17, 1E+17, 1E+17)
max = Point3dFromXYZ(-1E+17, -1E+17, -1E+17)
For i = 0 To UBound(cPoints)
If cPoints(i).X > max.X Then max.X = cPoints(i).X
If cPoints(i).Y > max.Y Then max.Y = cPoints(i).Y
If cPoints(i).Z > max.Z Then max.Z = cPoints(i).Z
If cPoints(i).X < min.X Then min.X = cPoints(i).X
If cPoints(i).Y < min.Y Then min.Y = cPoints(i).Y
If cPoints(i).Z < min.Z Then min.Z = cPoints(i).Z
Next
cSize = Point3dFromXYZ(0, max.Y – min.Y, 0)
cSize.Y = cSize.Y * -1.2
End Sub
Sub Casteljau()
Dim i As Long
Dim k As Double
Dim p As Long
Dim points() As Point3d ‘last parent point collection
Dim dPoints() As Point3d ‘division points
Dim mPoints() As Point3d ‘points to draw
Dim lineString As Element
Dim color As Long
Dim count As Long
Dim moveCount As Long
ReDim bPoints(0)
bPoints(0) = cPoints(0)
count = 0
moveCount = 0
For k = 1 / (div * cDiv) To 1 Step 1 / (div * cDiv) ‘k is scale factor of divisions
points = cPoints
dPoints = cPoints
color = 48
‘calculate divisions
While UBound(dPoints) > 1
‘points is the collection of vertices of the parent linestring
‘dPoints is the child linestring at scalefactor k
For i = 0 To UBound(points) – 1
dPoints(i) = Point3dAdd(Point3dScale(Point3dSubtract(points(i + 1), points(i)), k), points(i))
Next i
ReDim Preserve dPoints(UBound(points) – 1)
‘draw guidlines
If count = div Then
mPoints = dPoints
‘calculate offset
For p = 0 To UBound(mPoints)
mPoints(p) = Point3dAdd(mPoints(p), Point3dScale(cSize, moveCount))
Next
‘draw line
Set lineString = CreateLineElement1(Nothing, mPoints)
lineString.color = color
lineString.LineStyle = ActiveDesignFile.LineStyles(3)
ActiveModelReference.AddElement lineString
lineString.Redraw
color = color + 48
End If
points = dPoints
Wend
count = count + 1
‘draw progress of bezier curve
If count > div Then
count = 0
‘copy control polygon
Set lineString = ActiveModelReference.CopyElement(cLine)
Call lineString.Move(Point3dScale(cSize, moveCount))
ActiveModelReference.AddElement lineString
lineString.Redraw
moveCount = moveCount + 1
‘calculate offset of beziers pline
mPoints = bPoints
For p = 0 To UBound(mPoints)
mPoints(p) = Point3dAdd(mPoints(p), Point3dScale(cSize, moveCount – 1))
Next
‘draw bezier progress
Set lineString = CreateLineElement1(Nothing, mPoints)
lineString.color = 3
lineString.LineWeight = 2
ActiveModelReference.AddElement lineString
lineString.Redraw
End If
‘add calculated division point to collection of bezier points
ReDim Preserve bPoints(UBound(bPoints) + 1)
bPoints(UBound(bPoints)) = Point3dAdd(Point3dScale(Point3dSubtract(points(1), points(0)), k), points(0))
Next k
‘draw final bezier curve
mPoints = bPoints
For p = 0 To UBound(mPoints)
mPoints(p) = Point3dAdd(mPoints(p), Point3dScale(cSize, moveCount – 1))
Next
Set lineString = CreateLineElement1(Nothing, mPoints)
lineString.color = 3
lineString.LineWeight = 2
ActiveModelReference.AddElement lineString
lineString.Redraw
End Sub
Sub Main()
If ActiveModelReference.AnyElementsSelected Then
ScanDesignFile
getSize
Casteljau
End If
End Sub


















