OpenOffice.org Forum at OOoForum.orgThe OpenOffice.org Forum
 
 [Home]   [FAQ]   [Search]   [Memberlist]   [Usergroups]   [Register
 [Profile]   [Log in to check your private messages]   [Log in

Drawing Bezier shapes

 
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Code Snippets
View previous topic :: View next topic  
Author Message
DannyB
Moderator
Moderator


Joined: 02 Apr 2003
Posts: 3991
Location: Lawrence, Kansas, USA

PostPosted: Tue Jan 13, 2004 3:12 pm    Post subject: Drawing Bezier shapes Reply with quote

This message demonstrates how to draw some Bezier shapes in OOo Basic.

In section 9.3.2 of the Developer's Guide

http://api.openoffice.org/docs/DevelopersGuide/Drawing/Drawing.htm#1+3+2+1+Bezier+Shapes

there is a discussion of Bezier shapes in the Drawing document.

If you scroll down just a bit, you almost immediately run into a Java program example program.

Here is a Basic translation of that program. It draws the same thing as in the Developer's Guide.

I have added comments, and I daresay this one is easier to understand. I have also copied some comments from the java example in the developers guide.

Simply copy and paste this into Basic.

Code:
Sub Main
   ' Create a drawing document.
   oDrawDoc = StarDesktop.loadComponentFromURL( "private:factory/sdraw", "_blank", 0, Array() )
   ' Get its first page.
   oDrawPage = oDrawDoc.getDrawPages().getByIndex( 0 )
   
   ' Create a ClosedBezierShape.
   oPolyPolygonBezier = oDrawDoc.createInstance( "com.sun.star.drawing.ClosedBezierShape" )
   ' Add it to the draw page.
   oDrawPage.add( oPolyPolygonBezier )
   ' At this point, the shape doesn't describe anything.
   ' Somewhere below, you'll see a line where we assign to the PolyPolygonBezier
   '  property of this shape.  That is where this shape now becomes visible.
   
   ' Now create...
   '  An array of arrays of points
   '  An array of arrays of flags
   
   ' Set this PolyPolygon to have sixteen single polygons,
   '  containing four points each.
   ' The PolyPolygon total point count will be 64.
   ' If control points are used, they are allowed to appear as a pair only.
   ' Before and after such a pair must be a normal point.
   ' A bezier point sequence looks like...
   '  (n=normal, c=control): n c c n c c n n c c n
   nPolygonCount = 16
   nPointCount = 4
   nWidth = 10000
   nHeight = 10000
   
   ' These are the "arrays of arrays"
   aCoords = DimArray( nPolygonCount-1 )
   aFlags = DimArray( nPolygonCount-1 )
   
   nY = 0
   nHeightPerPolygon = Int( nHeight / nPolygonCount )
   For i = 0 To nPolygonCount-1
      ' Create an array of four points.
      ' A normal point, a control point, a control point and a normal point.
      oPoints = Array(_
                  MakePoint( 0, nY ),_
                  MakePoint( nWidth / 2, nHeight ),_
                  MakePoint( nWidth / 2, nHeight ),_
                  MakePoint( nWidth, nY ) _
                  )
      ' Create an array of flags.
      oFlags = Array(_
                  com.sun.star.drawing.PolygonFlags.NORMAL,_
                  com.sun.star.drawing.PolygonFlags.CONTROL,_
                  com.sun.star.drawing.PolygonFlags.CONTROL,_
                  com.sun.star.drawing.PolygonFlags.NORMAL _
                  )
      
      ' Add the oPoints array as one more element of
      '  the aCoords array of arrays.
      aCoords(i) = oPoints()
      
      ' Add the oFlags array as one more element of
      '  the aFlags array of arrays.
      aFlags(i) = oFlags()
      
      nY = nY + nHeightPerPolygon
   Next
   
   ' Create the PolyPolygonBezierCoords struct.
   oCoords = createUnoStruct( "com.sun.star.drawing.PolyPolygonBezierCoords" )
   ' Plug in the two arrays of arrays into its members.
   oCoords.Coordinates = aCoords
   oCoords.Flags = aFlags

   ' Now assign this struct to the shape we created earlier.
   ' Poof! the shape is now visible and has a size.
   oPolyPolygonBezier.PolyPolygonBezier = oCoords
   
   ' Now that the shape has a size, let's center it on the page.
   oPolyPolygonBezier.Position = _
            MakePoint( oDrawPage.Width / 2 - oPolyPolygonBezier.Size.Width / 2, _
                     oDrawPage.Height / 2 - oPolyPolygonBezier.Size.Height / 2 )
End Sub


'----------
'   Create and return a new Point object.
'
'   This is syntax sugar to make it easy to
'    create a com.sun.star.awt.Point object.
'
Function MakePoint( x As Long, y As Long ) As com.sun.star.awt.Point
   aPoint = createUnoStruct( "com.sun.star.awt.Point" )
   aPoint.x = x
   aPoint.y = y
   MakePoint() = aPoint
End Function


Here is another post over in the Macros and API section that I gave earlier.

FYI....Example use of Bezier curves in Draw macro
http://www.oooforum.org/forum/viewtopic.php?t=4745

This one draws 100 random Bezier shapes. If you scroll down a couple replies in that topic, you can figure out what the bezier shapes are before you run the program. Smile Or simply copy, paste and run the code from that posting if you want a surprise.

Here is a related article...

Draw: Introduction to draw and basic shapes
http://www.oooforum.org/forum/viewtopic.php?t=5383
_________________
Want to make OOo Drawings like the colored flower design to the left?


Last edited by DannyB on Thu Mar 25, 2004 7:38 am; edited 2 times in total
Back to top
View user's profile Send private message
DannyB
Moderator
Moderator


Joined: 02 Apr 2003
Posts: 3991
Location: Lawrence, Kansas, USA

PostPosted: Sat Feb 14, 2004 9:13 am    Post subject: Reply with quote

Building upon the above program, and also the Valentines program over at...
http://www.oooforum.org/forum/viewtopic.php?t=4745

I have built an even more elegant way to draw Bezier shapes. Try this example...

Code:
Sub Main
   ' Shorter constant names, just to make the code below easier to read.
   POINT_NORMAL = com.sun.star.drawing.PolygonFlags.NORMAL
   POINT_CONTROL = com.sun.star.drawing.PolygonFlags.CONTROL
   
   ' Create the object which holds geometry description of a poly-polygon.
   oCoords = createUnoStruct( "com.sun.star.drawing.PolyPolygonBezierCoords" )
   
   ' Add one polygon (bezier polygon)
   PolyPoly_BeginPoly( oCoords )
   PolyPoly_AddPoint( oCoords, MakePoint( 1000, 1000 ), POINT_NORMAL )
   PolyPoly_AddPoint( oCoords, MakePoint( 3000, 4000 ), POINT_CONTROL )
   PolyPoly_AddPoint( oCoords, MakePoint( 3000, 4000 ), POINT_CONTROL )
   PolyPoly_AddPoint( oCoords, MakePoint( 5000, 1000 ), POINT_NORMAL )
   
   ' Add another polygon (bezier polygon)
   PolyPoly_BeginPoly( oCoords )
   PolyPoly_AddPoint( oCoords, MakePoint( 1000, 2000 ), POINT_NORMAL )
   PolyPoly_AddPoint( oCoords, MakePoint( 3000, 6000 ), POINT_CONTROL )
   PolyPoly_AddPoint( oCoords, MakePoint( 3000, 6000 ), POINT_CONTROL )
   PolyPoly_AddPoint( oCoords, MakePoint( 5000, 2000 ), POINT_NORMAL )

   ' Create a new drawing. get its first drawing page.
   oDoc = StarDesktop.loadComponentFromURL( "private:factory/sdraw", "_blank", 0, Array() )
   oDrawPage = oDoc.getDrawPages().getByIndex( 0 )
   
   ' For extra credit...  try these two lines instead of the previous two lines.
'   oDoc = StarDesktop.loadComponentFromURL( "private:factory/swriter", "_blank", 0, Array() )
'   oDrawPage = oDoc.getDrawPage()
   ' Or try these...
'   oDoc = StarDesktop.loadComponentFromURL( "private:factory/scalc", "_blank", 0, Array() )
'   oDrawPage = oDoc.getSheets().getByName( "Sheet1" ).getDrawPage()
   
   ' Create the shape.
   oPolyPolygonBezier = oDoc.createInstance( "com.sun.star.drawing.ClosedBezierShape" )
   ' Add it to page.
   oDrawPage.add( oPolyPolygonBezier )
   ' Set its geometry.
   oPolyPolygonBezier.PolyPolygonBezier = oCoords
End Sub



'   Convenient way to build up a PolyPolygonBezierCoords structure.


' Call this to start a new polygon of points.
Sub PolyPoly_BeginPoly( oCoords As com.sun.star.drawing.PolyPolygonBezierCoords )
   aArrayOfArrayPoints = oCoords.Coordinates
   aArrayOfArrayFlags = oCoords.Flags
   Array1_AppendElement( aArrayOfArrayPoints, Array() )
   Array1_AppendElement( aArrayOfArrayFlags, Array() )
   oCoords.Coordinates = aArrayOfArrayPoints
   oCoords.Flags = aArrayOfArrayFlags
End Sub

' Call this to add a point, and flag, to the currently open polygon.
Sub PolyPoly_AddPoint( oCoords As com.sun.star.drawing.PolyPolygonBezierCoords,_
         ByVal oNewPoint As com.sun.star.awt.Point,_
         ByVal nNewFlag As Long )
   aArrayOfArrayPoints = oCoords.Coordinates
   aArrayOfArrayFlags = oCoords.Flags
   
   nNumPolys = Array1_Size( aArrayOfArrayPoints )

   aPoints = aArrayOfArrayPoints( nNumPolys - 1 )
   aFlags = aArrayOfArrayFlags( nNumPolys - 1 )
   
   Array1_AppendElement( aPoints, oNewPoint )
   Array1_AppendElement( aFlags, nNewFlag )
   
   aArrayOfArrayPoints( nNumPolys - 1 ) = aPoints
   aArrayOfArrayFlags( nNumPolys - 1 ) = aFlags
   
   oCoords.Coordinates = aArrayOfArrayPoints
   oCoords.Flags = aArrayOfArrayFlags
End Sub



'--------------------
' Return the number of elements in a single dimensional array.
' Typically this array was created by calling Array().
Function Array1_Size( aArray ) As Long
   On Error GoTo ErrorHandler
      nNumElements = UBound( aArray ) + 1
      Array1_Size() = nNumElements
      Exit Function
   
   ErrorHandler:
      Array1_Size() = 0
End Function


'--------------------
' Append a new element onto the end of a single dimensional array.
' Typically this array was created by calling Array().
' Example:
'   aArray = Array()
'   Array1_AppendElement( aArray, "Red" )
'   Array1_AppendElement( aArray, "Orange" )
'   Array1_AppendElement( aArray, "Yellow" )
' is the same as writing...
'   aArray = Array( "Red", "Orange", "Yellow" )
' is the same as writing...
'   Dim aArray( 2 )
'   aArray( 0 ) = "Red"
'   aArray( 1 ) = "Orange"
'   aArray( 2 ) = "Yellow"
' except in the last example, aArray is statically known by the
'  compiler to be an array, so you must always use parenthesis
'  when passing the array to a function.
'
Sub Array1_AppendElement( aArray, uNewElement )
   nNumElements = Array1_Size( aArray )
   If nNumElements = 0 Then
      aArray = Array( uNewElement )
   Else
      Redim Preserve aArray( nNumElements )
      aArray( nNumElements ) = uNewElement
   EndIf
End Sub



Function MakePoint( ByVal x As Long, ByVal y As Long ) As com.sun.star.awt.Point
   oPoint = createUnoStruct( "com.sun.star.awt.Point" )
   oPoint.X = x
   oPoint.Y = y
   MakePoint() = oPoint
End Function




By the way, from slashdot...

Roses are #FF0000
Violets are #0000FF
All of my base
are belong to you.

Happy Valentines day. Smile
_________________
Want to make OOo Drawings like the colored flower design to the left?


Last edited by DannyB on Thu Mar 25, 2004 7:41 am; edited 1 time in total
Back to top
View user's profile Send private message
SergeM
Super User
Super User


Joined: 09 Sep 2003
Posts: 3211
Location: Troyes France

PostPosted: Mon Feb 16, 2004 10:02 pm    Post subject: Reply with quote

Very interesting. It's hard for me to understand your PolyPoly_BeginPoly I guess what it does but I am completly unable to write such code. I have to work on arrays...
I will reuse this code with OpenBezierShape : I want to write a Sub which best fits data with Bezier curves.
_________________
Linux & Windows OOo3.0
UNO & C++ : WIKI
http://wiki.services.openoffice.org/wiki/Using_Cpp_with_the_OOo_SDK
In French
http://wiki.services.openoffice.org/wiki/Documentation/FR/Cpp_Guide
Back to top
View user's profile Send private message Visit poster's website
DannyB
Moderator
Moderator


Joined: 02 Apr 2003
Posts: 3991
Location: Lawrence, Kansas, USA

PostPosted: Tue Feb 17, 2004 6:26 am    Post subject: Reply with quote

sergeM wrote:
Very interesting. It's hard for me to understand your PolyPoly_BeginPoly I guess what it does but I am completly unable to write such code. I have to work on arrays...


Here is a brief explanation.

oCoords is a struct with two properties (1) Coordinates and (2) Flags.

Every Coordinate (i.e. Point made by MakePoint) has a corresponding Flag. So let's only talk about the Coordinates, since the structure of the Flags exactly mirrors it.

The oCoords.Coordinates is an Array of Arrays of Points. Sort of like this, from other examples...
Code:
oCoords.Coordinates = Array(_
   Array(_
      MakePoint( .... ),_
      MakePoint( .... ),_
      MakePoint( .... ) )_
   Array(_
      MakePoint( .... ),_
      MakePoint( .... ),_
      MakePoint( .... ) )_
   Array(_
      MakePoint( .... ),_
      MakePoint( .... ),_
      MakePoint( .... ) )_
   Array(_
      MakePoint( .... ),_
      MakePoint( .... ),_
      MakePoint( .... ) ) )


When you first create oCoords using createUnoStruct(), there are not even any arrays in the two memebers Coordinates and Flags.

So the first call to PolyPoly_BeginPoly sees that the length of the outer array is zero. It creates the first entry, as an empty inner array.

So at first, oCoords looks like this...
Code:
oCoords.Coordinates = <null>

After the first call to PolyPoly_BeginPoly, oCoords looks like this.
Code:
oCoords.Coordinates = Array( Array() )

When you call PolyPoly_AddPoint, then it looks like this...
Code:
oCoords.Coordinates = Array( Array( MakePoint( .... ) ) )

When you call PolyPoly_AddPoint again, then it looks like this...
Code:
oCoords.Coordinates = Array(_
   Array(_
      MakePoint( .... ),_
      MakePoint( .... ) ) )

When you call PolyPoly_BeginPoly again, it now looks like this...
Code:
oCoords.Coordinates = Array(_
   Array(_
      MakePoint( .... ),_
      MakePoint( .... ) ),_
   Array() )

When you call PolyPoly_AddPoint again, then it looks like this...
Code:
oCoords.Coordinates = Array(_
   Array(_
      MakePoint( .... ),_
      MakePoint( .... ) ),_
   Array(_
      MakePoint( .... ) ) )

I think you can see the pattern.

Learning the Lisp programming language will profoundly alter the way you think about programming for the rest of your days. (And for the better!)
_________________
Want to make OOo Drawings like the colored flower design to the left?


Last edited by DannyB on Thu Mar 25, 2004 7:25 am; edited 4 times in total
Back to top
View user's profile Send private message
SergeM
Super User
Super User


Joined: 09 Sep 2003
Posts: 3211
Location: Troyes France

PostPosted: Tue Feb 17, 2004 7:15 am    Post subject: Reply with quote

OK thank you very much for the explanation. I have one hour free to try some things around your work.
_________________
Linux & Windows OOo3.0
UNO & C++ : WIKI
http://wiki.services.openoffice.org/wiki/Using_Cpp_with_the_OOo_SDK
In French
http://wiki.services.openoffice.org/wiki/Documentation/FR/Cpp_Guide
Back to top
View user's profile Send private message Visit poster's website
jpvanhoy
Newbie
Newbie


Joined: 21 Oct 2008
Posts: 3

PostPosted: Fri Jan 16, 2009 11:29 am    Post subject: Reply with quote

Just a side note:

The document Danny refers to in his first post above as:
http://api.openoffice.org/docs/DevelopersGuide/Drawing/Drawing.htm#1+3+2+1+Bezier+Shapes

has now moved to:
http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/Drawings/Bezier_Shapes

Carry on,
J
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Code Snippets All times are GMT - 8 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group