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

Draw: Introduction to draw and basic shapes
Goto page Previous  1, 2
 
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Code Snippets
View previous topic :: View next topic  
Author Message
broxtor
General User
General User


Joined: 02 Nov 2004
Posts: 10
Location: The Netherlands

PostPosted: Sun Nov 07, 2004 1:40 am    Post subject: Reply with quote

Hi Danny,

I was playing around with your examples from the first post and ran into a problem that I'm able to solve. When I try to draw a line (or rectangle or all the others) from sub Main it works like a charm. But when I create another sub, e.g. sub drawline, and try to draw the shapes from there I get an error message saying that the object variable is not set. How can I solve this. The code I'm trying to execute is listed below.

Code:

Sub Main
oDrawDoc = StarDesktop.loadComponentFromURL( "private:factory/sdraw", "_blank", 0, Array() )
    oDrawPage = oDrawDoc.getDrawPages().getByIndex( 0 )
call DrawLine
End Sub

Sub DrawLine
    oShape = MakeLineShape( oDrawDoc, MakePoint( 1000, 1000 ), MakeSize( 2000, 3000 ) )
    oDrawPage.add( oShape )
End Sub

 Function MakePoint( x As Long, y As Long ) As com.sun.star.awt.Point
    Dim aPoint As New com.sun.star.awt.Point
    aPoint.x = x
    aPoint.y = y
    MakePoint() = aPoint
 End Function

 Function MakeSize( width As Long, height As Long ) As com.sun.star.awt.Size
    Dim aSize As New com.sun.star.awt.Size
    aSize.width = width
    aSize.height = height
    MakeSize() = aSize
 End Function

 Function MakeLineShape( oDrawDoc As Object, Optional position As com.sun.star.awt.Point, Optional size As com.sun.star.awt.Size ) As com.sun.star.drawing.LineShape
    oShape = oDrawDoc.createInstance( "com.sun.star.drawing.LineShape" )
    If Not IsMissing( position ) Then
       oShape.Position = position
    EndIf
    If Not IsMissing( size ) Then
       oShape.Size = size
    EndIf
    MakeLineShape() = oShape
 End Function


_________________
Thanks for the help!!
Back to top
View user's profile Send private message
DannyB
Moderator
Moderator


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

PostPosted: Sun Nov 07, 2004 10:55 am    Post subject: Reply with quote

Your DrawLine subroutine does not have access to the oDrawDoc or oDrawPage variables.

A DrawLine subroutine should have a parameter list like this....

Sub DrawLine( oDrawDoc, oDrawPage, x1, y2, x2, y2 )

The subroutine would draw a line from x1,y1 to x2,y2. I have common subroutines like this in my library. Then when I want to draw lines, I write things like...

DrawLine( oDrawDoc, oDrawPage, 1000,1000, 3000,5000 )

You can even layer an entire Turtle Graphics type API on top of this. See my Turtle Graphics Tutorial. I think you can get it at OOoMacros.org.

Using Turtle Grpahics, you can easily draw lines into complex shapes, such as the "Spirograph" type figure to the left of this message.

For lots more example Drawing code see...

Danny's Draw Power Tools

Random Drawings
Hint: this one draws lots of random Christmas Trees, Valentimes, and Flowers.

Finally, be sure to see my Danny's Library which is quite outdated at this point, but has lots of useful routines, such as the DrawLine type routine, and lots of other DrawXXX routines.

See where I defined a DrawLine subroutine earlier in this thread here....
http://www.oooforum.org/forum/viewtopic.php?p=28408#28408
Copy and paste, then run the entire example to see how it works. It draws some lines on page 3. It draws into an Impress document, but you can change this into a Draw document by simply changing "private:factory/simpress" into "private:factory/sdraw".

I have written extensively about how to program Draw. See the many examples in this thread and the OOoMacros.org examples I linked to above.
_________________
Want to make OOo Drawings like the colored flower design to the left?
Back to top
View user's profile Send private message
broxtor
General User
General User


Joined: 02 Nov 2004
Posts: 10
Location: The Netherlands

PostPosted: Sun Nov 07, 2004 11:23 am    Post subject: Reply with quote

Thanks Danny. It works now.
I really like all your examples and tutorials. They are very helpfull in learning Basic with OOo.

One more little question though: In your code examples you use _ to break up one line into several others. For some reason my OOo doesn't like this and gives me an error. Than I have to put everything on one line, which isn't so pretty. Do you have a solution to this also by any chance?
_________________
Thanks for the help!!
Back to top
View user's profile Send private message
DannyB
Moderator
Moderator


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

PostPosted: Sun Nov 07, 2004 12:22 pm    Post subject: Reply with quote

Be sure that the underscore is the very last character of the line. If you have a space after the underscore, then it won't work.

When you copy code from an article in a web browser, you may end up with spaces after the underscores.
_________________
Want to make OOo Drawings like the colored flower design to the left?
Back to top
View user's profile Send private message
broxtor
General User
General User


Joined: 02 Nov 2004
Posts: 10
Location: The Netherlands

PostPosted: Sun Nov 07, 2004 1:09 pm    Post subject: Reply with quote

Thanks again! Sometimes things can be so simple......
_________________
Thanks for the help!!
Back to top
View user's profile Send private message
Cybb20
Super User
Super User


Joined: 02 Mar 2004
Posts: 1569
Location: Frankfurt, Germany

PostPosted: Tue Nov 09, 2004 7:23 pm    Post subject: Reply with quote

Hi DannyB, sorry for interfering in this thread Smile but I just wanted to show people my version of making shapes. It's a general what I would consider 'performance' function, that is it has no Optional parameters (believe it or not, but it makes a difference in performance when dealing with bigger projects) and it uses the Erase keyword to efficiently delete objects that are not needed anymore. Or more precisely, it releases the reference count for that object.

Here is the function that works for all shapes, you just pass the servicename (if you're only dealing with RectangleShape then this is not for you, if you're instead using several different shapes this might be more appropriate then):
Code:

Function MakeShape(      KindOfShape as String,_
                   ByRef pos As com.sun.star.awt.Point,_
                   ByRef size As com.sun.star.awt.Size    )
                         
 oShape = thisComponent.createInstance(KindOfShape)
 oShape.Position = pos
 Erase pos
   
 oShape.Size = size
 Erase size
   
 MakeShape = oShape

End Function


Also this function deals only with one document, the current one! So if you're having more than one to deal with then passing in the document as the first parameter would be more suitable.

Christian
_________________
- Knowledge is Power -
Back to top
View user's profile Send private message Send e-mail
DannyB
Moderator
Moderator


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

PostPosted: Tue Nov 09, 2004 8:29 pm    Post subject: Reply with quote

Your routine seems nominally faster. When drawing 1000 rectangles, your routine seems to be between zero and two seconds faster. This, strangely, with or without the two Erase statements. Commenting out the two Erase statements seems to make no measurable difference.

This actually makes sense. If you didn't do the Erase, then the reference counters of the size and pos get decremented anyway when the function ends and the two variables go out of scope. So all Erase does is release the two references sooner. In other words, the same workload, just rearranged as to when the two references are released.

So discounting the Erase as being the reason for the performance difference, this being evidenced by actual time trials, I can't really explain why your function would be slightly faster. On my machine, your routine takes about six to eight milliseconds, while mine is about seven to nine milliseconds. Not a big difference, but when done 1000 times, it makes up to a couple seconds difference.

I'm on SuSE 9.1, Athlon XP 1800, 256 MB ram, with about 145 MB paged out to swap.

Code:
Sub Main
'   oDoc = StarDesktop.loadComponentFromURL( "private:factory/sdraw", "_blank", 0, Array() )
   oDoc = ThisComponent

   nStart1 = Timer
   Test1( oDoc )
   nEnd1 = Timer
   
   nStart2 = Timer
   Test2( oDoc )
   nEnd2 = Timer
   
   Print "Time1 "; nEnd1-nStart1; " seconds.  Time2 "; nEnd2-nStart2; " seconds"
End Sub

Sub Test1( oDoc )
'   oDoc = StarDesktop.loadComponentFromURL( "private:factory/sdraw", "_blank", 0, Array() )
   oDrawPage = oDoc.getDrawPages().getByIndex( 0 )
   For i = 1 To 1000
      oShape = MakeRectangleShape( oDoc, MakePoint( i*10+1000, i*12+2000 ), MakeSize( 1000, 1000 ) )
      oDrawPage.add( oShape )
   Next
End Sub

Sub Test2( oDoc )
'   oDoc = StarDesktop.loadComponentFromURL( "private:factory/sdraw", "_blank", 0, Array() )
   oDrawPage = oDoc.getDrawPages().getByIndex( 0 )
   For i = 1 To 1000
      oShape = MakeShape( oDoc, "com.sun.star.drawing.RectangleShape", MakePoint( i*10+6000, i*12+2000 ), MakeSize( 1000, 1000 ) )
      oDrawPage.add( oShape )
   Next
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
   Dim aPoint As New com.sun.star.awt.Point
   aPoint.x = x
   aPoint.y = y
   MakePoint() = aPoint
End Function


'----------
'   Create and return a new Size object.
'
'   This is syntax sugar to make it easy to
'    create a com.sun.star.awt.Size object.
'
Function MakeSize( width As Long, height As Long ) As com.sun.star.awt.Size
   Dim aSize As New com.sun.star.awt.Size
   aSize.width = width
   aSize.height = height
   MakeSize() = aSize
End Function



'----------
'   Create and return a RectangleShape object.
'
'   After you create the shape object, you can manipulate
'    its properties to alter its appearance, including
'    its size and location.
'
'   You must pass the document object.
'   Optionally, you may also pass in a location and size.
'   If you do not, then the new object has size (0,0)
'    and location (0,0), which is the extreme upper left.
'    In other words, the object is squished way up in the
'    upper left corner, and has no size, therefore cannot be seen.
'
Function MakeRectangleShape( oDrawDoc As Object,_
               Optional position As com.sun.star.awt.Point,_
               Optional size As com.sun.star.awt.Size ) As com.sun.star.drawing.RectangleShape
   oShape = oDrawDoc.createInstance( "com.sun.star.drawing.RectangleShape" )
   If Not IsMissing( position ) Then
      oShape.Position = position
   EndIf
   If Not IsMissing( size ) Then
      oShape.Size = size
   EndIf
   MakeRectangleShape() = oShape
End Function


Function MakeShape( oDrawDoc As com.sun.star.drawing.DrawingDocument,_
                  KindOfShape as String,_
                  ByRef pos As com.sun.star.awt.Point,_
                  ByRef size As com.sun.star.awt.Size )                       
   oShape = oDrawDoc.createInstance(KindOfShape)
   oShape.Position = pos
   Erase pos
      
   oShape.Size = size
   Erase size
      
   MakeShape = oShape
End Function



Things I tried.
1. Create a new document once, and run both tests on that document.
2. Run both tests on ThisComponent.
3. Make each test create its own new document.

Note that I modified your function slightly to pass in the drawing document. Without this parameter, I would expect your function to gain a wee bit more performance edge.

Ignoring the Erase, which measurably seems to make no difference, what do you believe accounts for your performance edge?

When I was writing my functions....
MakeLineShape
MakeRectangleShape
MakeEllipseShape
etc. etc.
I had considered an approach of passing in the service name as a string. The reason I went against this is that I thought it improved the readability of the calling code. On each call, I still must specify what kind of shape to create. Instead of doing that with a service name string, I do it as part of the function name. I would have honestly expected having hardcoded service names to be a performance advantage.

Wait a minute.... idea...

Okay, I just figured it out. It is my Optional parameters. When I rewrite my MakeRectangleShape to this....
Code:
Function MakeRectangleShape( oDrawDoc As Object,_
               ByRef position As com.sun.star.awt.Point,_
               ByRef size As com.sun.star.awt.Size ) As com.sun.star.drawing.RectangleShape
   oShape = oDrawDoc.createInstance( "com.sun.star.drawing.RectangleShape" )
      oShape.Position = position
      oShape.Size = size
   MakeRectangleShape() = oShape
End Function

My MakeRectangleShape function runs as fast as yours. With or without the two Erase statements -- which make sense to me. So the Optional parameters, or maybe the two IF statements are what make up the difference.

The lesson here is that my functions can be modified to perform better. I think I never take advantage of the fact that the parameters are optional. So maybe I should reconsider the Optional parameters?

I believe that hardcoding the service name inside the function, and having multiple shape functions is a better practice, for several reasons.
1. It reads better in the code calling the library routines
2. It should perform better. Rather than passing in an additional string parameter that is a service name, the shape type "parameter" is actually part of the function name, therefore, there is one less parameter.

It reads better, because imagine this....

Code:

oShape = MakeShape( "com.sun.star.drawing.RectangleShape", MakePoint(), MakeSize() )
oShape = MakeShape( "com.sun.star.drawing.RectangleShape", MakePoint(), MakeSize() )
oShape = MakeShape( "com.sun.star.drawing.RectangleShape", MakePoint(), MakeSize() )
oShape = MakeShape( "com.sun.star.drawing.RectangleShape", MakePoint(), MakeSize() )


vs...

Code:

oShape = MakeRectangleShape( MakePoint(), MakeSize() )
oShape = MakeRectangleShape( MakePoint(), MakeSize() )
oShape = MakeRectangleShape( MakePoint(), MakeSize() )
oShape = MakeRectangleShape( MakePoint(), MakeSize() )
oShape = MakeRectangleShape( MakePoint(), MakeSize() )
oShape = MakeRectangleShape( MakePoint(), MakeSize() )
oShape = MakeRectangleShape( MakePoint(), MakeSize() )


In the above, I left out the oDrawDoc parameter for brevity.

Your function led me to do a lot of interesting analysis and reconsideration.
_________________
Want to make OOo Drawings like the colored flower design to the left?
Back to top
View user's profile Send private message
Cybb20
Super User
Super User


Joined: 02 Mar 2004
Posts: 1569
Location: Frankfurt, Germany

PostPosted: Wed Nov 10, 2004 6:54 am    Post subject: Reply with quote

Quote:
1. It reads better in the code calling the library routines
2. It should perform better. Rather than passing in an additional string parameter that is a service name, the shape type "parameter" is actually part of the function name, therefore, there is one less parameter.


1. I disagree, one just has too look into the string and there it is. From an overall objective of the examples given I can read MakeShape("servicename"...) better than MakeRectangleShape(...)

2. That might be correct, although probably only a tiny difference. I am glad you did these extensive tests.

I want to add that the MakeShape() function, although it might be weaker in regards of point 2, it is more general. People don't need to write many functions for drawing many kinds of shapes, thus the time they spend on writing code for several kinds of shapes will be much more reduced. It is often the time effort of writing the actual code, that people tend to forget, a very popular example being Python that heavily reduces this time, simply because often only certain things need a high execution speed and Python is in these situations able to extend itself with another language like C, C++.

Christian
_________________
- Knowledge is Power -
Back to top
View user's profile Send private message Send e-mail
DannyB
Moderator
Moderator


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

PostPosted: Wed Nov 10, 2004 8:37 am    Post subject: Reply with quote

Cybb20 wrote:
1. I disagree, one just has too look into the string and there it is.

Readability, that is probably just a matter of taste. Readability is in the eye of the beholder. To each their own.

Cybb20 wrote:
thus the time they spend on writing code for several kinds of shapes will be much more reduced.

I disagree with this. These functions are trivial. There are not that many shape services. I have not created any new shape draw functions in over a year. Rectangle, Ellipse, Line, Text. These four cover the vast majority of important uses. (i.e. Calendar creator, Danny's Draw Power Tools, etc.) Arcs are just Ellipses. The filled vs. hollow are just attributes of the shapes.

Polygons and Bezier-gons are best handled quite differently. GroupShape is handled entirely differently. I handle ControlShapes in a separate lib module that deals with forms (posted in earlier threads). That only leaves more obscure shapes, such as an AppletShape.

As I note below, these functions are trivial. If I needed, for instance, a MakeAppletShape, I would just clone it from MakeRectangleShape, and change the service name. No significant time spent.

I find any argument of a single shape function saving large amounts of programming time to be unconvincing.

Cybb20 wrote:
although it might be weaker in regards of point 2, it is more general

That is true. It is also something I considered when I first wrote my draw functions.

In fact, my first approach, which you can see if you go download extremely old versions of my library, was to have a general MakeShape function, and then the MakeRectangleShape function simply called MakeShape passing in the correct service name. Later, I did away with the general purpose MakeShape function, because each of these functions are trivial.

I wonder how badly the performance would have been for MakeRectangleShape calling MakeShape? Both MakeRectangleShape and MakeShape took Optional parameters. Smile



The end result of all of this, of course, is that we will end up with the best possible techniques for programming OOo drawings.
_________________
Want to make OOo Drawings like the colored flower design to the left?
Back to top
View user's profile Send private message
Cybb20
Super User
Super User


Joined: 02 Mar 2004
Posts: 1569
Location: Frankfurt, Germany

PostPosted: Wed Nov 10, 2004 8:23 pm    Post subject: Reply with quote

DannyB wrote:
Cybb20 wrote:
1. I disagree, one just has too look into the string and there it is.

Readability, that is probably just a matter of taste. Readability is in the eye of the beholder. To each their own.

I agree on this, we don't want to get into discussions like if K&R C style is the correct one or not (there have been a lot people talking about whether the brackets go here or there, rather than looking at more important things like consistency of variable-name giving).
Thus the decisions of readability are all up to the person seeing and comparing the two functions.

DannyB wrote:

Cybb20 wrote:
thus the time they spend on writing code for several kinds of shapes will be much more reduced.

I disagree with this. These functions are trivial. There are not that many shape services. I have not created any new shape draw functions in over a year. Rectangle, Ellipse, Line, Text. These four cover the vast majority of important uses. (i.e. Calendar creator, Danny's Draw Power Tools, etc.) Arcs are just Ellipses. The filled vs. hollow are just attributes of the shapes.
As I note below, these functions are trivial. If I needed, for instance, a MakeAppletShape, I would just clone it from MakeRectangleShape, and change the service name. No significant time spent.


If it is a year ago or not is a relative consideration, in the overall you still used more time than you would have for the MakeShape function. But again this is also relative to the needs of the one using the functions (ie does he always use a certain kind of shape, then he wouldn't have to write the servicename as first parameter and might be saving more time in the overall)

DannyB wrote:

The end result of all of this, of course, is that we will end up with the best possible techniques for programming OOo drawings.


Absolutely correct, as Marx said out of the thesis and antithesis comes the synthesis. That's why things need to be discussed and synthesis most commonly comes out of different standpoints of two people.
However I feel like for our discussion this is rather a tiny difference and is as stated above more up to the persons' own perspectives and views.

Christian
_________________
- Knowledge is Power -
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Code Snippets All times are GMT - 8 Hours
Goto page Previous  1, 2
Page 2 of 2

 
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