Change the size of a ink drawn line

Started by markem, April 18, 2014, 06:00:11 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

markem

Some years ago I tried to figure out how to make naturally looking rivers in Visio.  Unfortunately - all I did was frustrate myself and then to resign myself to not being able to do it.

But now I am back.  :-)

I have a new idea that may make it possible to at last do naturally looking rivers in Visio.  (I'm still using Visio 2003 by the way!)  Here is the idea:

Idea: If you use the line tool you can only do straight lines.  If you use the pencil tool then you can do nice curves.  But if you use the INK tools (ie: Ball point pen, etc...) you can produce natural looking drawings.  These drawings have to keep track of all of those points and places where you drew the line.  What I am wondering is - can you change the width of the line being drawn from the first point to the last between each of the successive points?  For instance, let's say I have a macro that brings up a box that asks you two questions:

Q1 = "Starting Width (default = 1pt)?
Q2 = "Ending Width (default = 10pt)?

So now I have a ratio.  For every 10% (ie: The difference between 1 & 10 is 10 [not 9 because you have to include the beginning and ending sizes]) of the way along the line from the beginning to the end the line width has to change by 1pt.  This would mean that the line would start out narrow and become wider over the distance it travels.  I was doing this by hand the other day when I thought I'd ask if this was possible.

I'm of two minds on this.  First - can it be done with just the standard INK item.  Second - if not, then how hard is it to convert the line to a shape.  When I do this by hand - I get one point for every change in the line (so I wind up with A LOT of points) but then I can move the individual points around to adjust my lines.  So if you can't change the width of an INK line on a segment by segment basis - would it be possible to convert it to a shape and then change each of _those_ segment's widths?

If none of the above is possible - like say only the whole line segment can be changed (ie: the INK shape can not be changed in this fashion nor can the INK->shape be changed because all of the points comprise a single shape still) - then can the converted shape be broken up into individual line segments so that each segment can be changed?

So - first - is the above possible and second - can you give me some hints on what I need to do in order to be able to just get to the right information?  I'm not a big VBA person.  More of a PHP person.  :-)

Thanks in advance for any help you can give.  :-)

See the attachment for an example of what I mean.

Yacine

Why not simply use a line patterns?
Put a triangle or a pyramid in the pattern and start drawing.
Yacine

markem

I've done that before and it works ok but not great.  I'm eventually looking to make the line randomize sizes increasing and decreasing according to a formulae for natually occurring rivers I developed.

wapperdude

The line pattern is still your best bet.  The custom pattern doesn't have to be simple, you can use the freeform tool to create some random, closed shape which can be filled.  Add to that a combination of a fill and shadow (shadow with no offset), and you can get a fairly creative coloring scheme.  Not sure that you can select specific sections of a random, freeform line.

Wapperdude
Visio 2019 Pro

markem

Yeah - that's the biggie.  I know an INK line can be converted to Geometric shape and that Geometric shape will have one point for every change in the line.  The real question is - can you break that line up, how to do that, and then can you change the line width of each of those segments.  I'm reading up on the Visio Programming for Dummies book online.  I'm thinking of buying it even though it is for 2007 and not 2003.  I'm sure a lot of the book is still relevant to what I want to do.

markem

I looked around and found the Microsoft SDK for Visio 2003.  It is full of examples on how to do various things in Visio.  For instance:

Public Sub DrawLine_Example()

    Dim vsoShape As Visio.Shape

    Set vsoShape = ActivePage.DrawLine(5, 4, 7.5, 1)

End Sub 


That is how easy it is to draw a line segment.  (0,0) is in the bottom left corner while (8.5,11) is in the upper right corner.  I did some reading up on being able to click the mouse and determine if it is down or up and found a very simple methodology to use.  Unfortunately, the example program given doesn't work.  It is split up in to two sections.  The first one is the class and the second is the program that goes into the location called ThisDocument.  However, the trigger for the program (Document_DocumentSaved) doesn't seem to do anything when you save the document.  That is to say that when you save the document it is supposed to trigger the program so that when you do a mousedown or mouseup or mousemove the script is supposed to tell you what you just did and instead - it doesn't do anything.  However, if I can get this to work then I can make a simple routine that would allow me to monitor key strokes also (like +/-) so I can increase/decrease the width of the line dynamically.  This would meet my needs well enough.  Make a bunch of small line segments, maybe have a minimum number of pixels/points away from the last point and to be able to increase/decrease the line width.  :-)

markem

Ok - I'm not one to complain constantly but......

Could they use the same terms in their names in Visio internals?  The command is:

Debug.Print "Left mouse button clicked"

But the Debug Window's name is : Immediate

Makes it kind of hard to find when you are trying to see the messages that are being printed.  But at last I have found it and the mouse stuff IS working!  :-)

So now all I have to do is to try to tie the two things together (ie: Follow the mouse when it is down and make lines every X number of pixels!).  Getting closer.  :-)

Yacine

Hi Markem,
can you send a sample of what you are trying to do?

I could not really make a sense of what you are writing.
Yacine

markem

#8
Ok - look at the map from Google Maps.  I want to be able to draw a river segment like the one on the map.  You can not do that with Visio 2003.  Or probably any of the versions of Visio up to the present.  It doesn't conform to any of the given tools such as rectangles, circles, arcs, and so forth.  The only thing you can use is the INK pens.  But even those only do one size line.  (ie: Whatever you set it to.)  You can't use a shape in a line pattern because they either repeat or do not repeat.  if they repeat the river looks like it is from 2D world or something like that.  If you do not repeat then the line just keeps getting larger.  That is not how rivers work.  They DO eventually become larger but they grow and shrink as they move along their paths and they have islands in the streams and other such things.  This naturally occurring set of pathways can not be duplicated easily in Visio.  Photoshop - yeah.  Illustrator - with a lot of work.  Could I just draw this by hand, scan it in, and then use Visio to trace over everything?  Why?  Why should I do that?  Visio is supposed to make our lives easier.  Yet Visio doesn't have any kind of naturally occurring set of commands.

This is like the difference between Painter and PhotoShop.  PhotoShop has GROWN into being able to do/use naturally occurring paints, brushes, and such but until Painter came along - no one ever thought about making Nozzles or oil paintings ON A COMPUTER.  Scan them in - yeah sure.  Touch up digital pictures - yep - they did that.  But be able to create from the ground up oil paintings, pastel paintings, chalk, pencil, variable pressure?  Nope.  Painter had to be created before everyone went "Wow!  That's neat!" and to write the code to do this.  Now - everyone has it.  Some are better programs than others.

Visio started out as just a plain CAD program (just like Canvas did at Deneba).  It evolved a bit in 2003 and now in 2013 there are a lot of things you can do artistically that you cuold not do in Visio 2003.  Just like Canvas 5 and 7 and now whatever number it is at - Canvas is more of an artistic program rather than a CAD program.  The problem is - what made Visio so great was it WAS a CAD program that did a lot more than most other CAD programs did.  So in Visio 2013 you've pretty much lost the CAD side of things and Visio is now mostly just another art program with a side dish of CAD.  But I like 2003 because it is mainly a CAD program.

So >MY< problem is that I want those naturally occurring types of abilities.  Like Campaign Cartographer (which I do own already) - I'd like to be able to make fractal landscapes, rivers, mountains, and things like that.  Campaign Cartographer is actually built on top of FastCAD.  A CAD system from Great Britian and you get FastCAD as part of Campaign Cartographer only certain parts of FastCAD are disabled.  The problem with FastCAD is that it is a VERY old DOS program that was given Windows capabilities.  And.......it works in reverse.  Like many of the old CAD systems you have to tell it everything up front AND THEN draw your figure.  It is a real pain in the rear to learn and use because of this.  People who, in the pre-computer age - learned how to do architectural drawings love it because it works in the same manner as how they were taught.  But I like Visio because it is straight forwards.  You draw what you want and then you can modify it as you go.  Campaign Cartographer - you are kind of stuck or you have to jump through hoops to make it work the way you want it to work.  It is sort of like GIMP.  When GIMP first came out it worked the same way as Campaign Cartographer.  Everything worked in reverse to how Photoshop worked.  Then someone came along and rewrote the interface and made it work in the same way that Photoshop worked.  So GIMP then worked in drive instead of reverse (to use automotive terminology).  Now GIMP just works that way and hardly anyone remembers when GIMP was very hard to use.

So I want to apply Visio's forwards thinking way of doing things to what I would do in Campaign Cargtographer.  I want to build mountains, valleys, rivers, towns, coastlines, and the like.  I want to be able to drag out a rectangular area and have Visio create a fractalized area.  I want to be able to create a fractal coastline and have Visio layout the additional fractalized ocean depth areas.  But to be able to do all of this I have to start somewhere and that somewhere is - I want to draw a realistic looking river that Visio does the grunt work for me and all I have to do is to draw a curvy line.  Visio does the rest.  I'd also like to be able to provide some inputs into the river creation.  I want to be able to expand the river when I want to, I want it to split when I want it to split, join when I want it to join, and to be able to put islands into the middle of the river when I want it to do so.  Starting point though - is just to draw a river like I can do with the INK command only this river is made up of lots of little line segments that I can move if need be.  The DrawPolyline example is what I have been looking for.  The first part of that example creates a polyline with multiple line segments and the DrawLine example just does on line segment.  So if I keep track of the array of X and Y locations (start-stop) and how wide I want each line segments - then I have my line drawing part and all I need to do is to capture the mouse movements, the up and down of the mouse buttons, and I can pretty much do the line drawings.

After I have gotten this to work - my next thing is to modify how the lines are drawn so they are like the Google map (ie: Dark blue edges and light blue centers).  And like Google Maps - if I do this as a shape (ie: polyline) then I can zoom in as far as I want or zoom out as far as I want too.  The line would still remain the same.

Does this explain what I am doing and wanting?  :-)

wapperdude

What you asking Visio to do isn't possible.  Visio, and most (if not all) Photo editing and drawing programs don't do fractals.  Certainly not Visio.  That was never its purpose.  For those effects, you need to import an image.  I doubt there's much demand for those features so don't expect to see them anytime soon.

Wapperdude
Visio 2019 Pro

markem

wapperdude:  As I said - FastCAD will do this under Campaign Cartographer.  Fractal Landscape is also used by game players, nBoss has a Fractal Terrain program, Dungeon Djinni is also a CAD program, MapX was a CAD program that handled this as well.  There is even a plug-in for AutoCAD that will do fractals.  There are well over 6 million D&D players and more than a million GURPS players.  Every year over $1 Billion dollars is spent on RPG games, accessories, and on going to conventions.  I think there is a target audience for this.  There were several small attempts to bring Visio into the RPG world but these were mainly some simple shapes to help people draw dungeons.  No one has ever done a fractal line.  Factals are what are used to create realistic flowers, coastlines, mountains, valleys, rivers, streams, trees, grass, and so forth.  The programs are fairly simple because fractals are recursive and thus - so are the programs that create them.

I'll see about posting an image when I am done with just the river drawer.

Yacine

 Hi Markem,
I fully agree with Wapperdude, that Visio was not intended for fractals. I think the better tool for your purpose is Inkscape. It is free and has many features to make a vector graphic look more handmade.
Why? Because Visio's graphics capabilities are honestly said, limited. Its strength comes when data have to be linked to graphics.
However your request is challenging, so here are some thoughts to get it done with Visio.
1)      Rivers
a) One simple way would be to draw the line of the river with the freeform tool. An appropriate offset will give the route a width. Connect the offset lines with small line segments and join.
The so created shape can now be edited by moving the vertex points. (s. Page 1)
b) Much more interesting is to setup some macros to create custom line patterns.
Inkscape has similar tools where the shape of a line can be edited via a separate shape (https://www.youtube.com/watch?v=BDcUKT3Bclo)
On page 2 I inserted some line shapes that you can be edited and inserted in duplicates of Master.x
Page 3 shows some freeform lines with these masters as line patterns.

The idea would now be to create on the fly a new pattern, whenever you need a new line. That should not be so difficult.
The big advantage over solution A, is that the path is still fully editable.
2) Fractals
I agree with your answer to Wapperdude. But that's an issue worth a separate thread and some preparation thoughts.
Yacine

markem

Ok - it took me a while to figure out the "Object Required" messages in the "Oh so helpful" help section.  And I actually finally went on line and found out what was the matter.  It turns out you can get this same message in multiple ways.  I managed to do it in two different ways.  The first way is to NOT have the word "SET" in front of assigning an object a value and the other way is to HAVE the SET command on a line where you are trying to set a variable.  So - keep that in mind if you decide to program VBA.  They reuse the same error messages for different reasons.  Anyway - here is a first whack at making it so you can draw a line out of multiple line segments.  I'm still trying to figure out how to get rid of the selection box.  But at least this work.

Main Program ( placed inside of the ThisDocument object):
Dim myMouseListener As MouseListener
Dim btnLocations(1000, 1000) As Double
Dim btnCount As Integer

Public Sub DrawLine_Example()

    Dim vsoShape As Visio.Shape
   
    Set myMouseListener = New MouseListener
   
    Debug.Print "Ready"
   
End Sub



MouseListener (taken from the CHM and modified):
Dim WithEvents vsoWindow As Visio.Window
Dim xc As Double
Dim yc As Double
Dim myButton As String
Dim btnLocations(1000, 1000) As Double
Dim btnCount As Long
Dim I As Long

Private Sub Class_Initialize()

    Set vsoWindow = ActiveWindow
    btnCount = 0
    myButton = "LU"
   
End Sub

Private Sub Class_Terminate()

    Set vsoWindow = Nothing

End Sub

Private Sub vsoWindow_MouseDown(ByVal Button As Long, ByVal KeyButtonState As Long, ByVal x As Double, ByVal y As Double, CancelDefault As Boolean)
   
    If Button = 1 Then
        myButton = "LD"
        btnCount = 0
        btnLocations(btnCount, 0) = x
        btnLocations(btnCount, 1) = y
        Debug.Print "Left mouse button clicked"
    ElseIf Button = 2 Then
        myButton = "MD"
        Debug.Print "Right mouse button clicked"
    ElseIf Button = 16 Then
        myButton = "RD"
        Debug.Print "Center mouse button clicked"
    End If
       
End Sub

Private Sub vsoWindow_MouseMove(ByVal Button As Long, ByVal KeyButtonState As Long, ByVal x As Double, ByVal y As Double, CancelDefault As Boolean)
    Debug.Print "x-position is "; x
    Debug.Print "y-position is "; y
    If (myButton = "LD") Then
        btnCount = btnCount + 1
        If (btnCount > 1000) Then btnCount = 1000
        btnLocations(btnCount, 0) = x
        btnLocations(btnCount, 1) = y
        Set vsoShape = ActivePage.DrawLine(btnLocations(btnCount - 1, 0), btnLocations(btnCount - 1, 1), btnLocations(btnCount, 0), btnLocations(btnCount, 1))
        End If
           
End Sub

Private Sub vsoWindow_MouseUp(ByVal Button As Long, ByVal KeyButtonState As Long, ByVal x As Double, ByVal y As Double, CancelDefault As Boolean)
   
    If Button = 1 Then
        myButton = "LU"
        Debug.Print "Left mouse button released"
    ElseIf Button = 2 Then
        myButton = "MU"
        Debug.Print "Right mouse button released"
    ElseIf Button = 16 Then
        myButton = "RU"
        Debug.Print "Center mouse button released"
    End If
       
    Set myMouseListener = Nothing
End Sub



Ok - if you have read this far - does anyone know why the Visio VBA editor won't scroll the edit window?  Maybe it's just a Visio 2003 thing - but I thought I remembered that the edit window scrolled via the middle mouse button up and down.  Let me know if you know how to make it do this.  Thanks!  :-)

Attached image was taken after I drew the line and then went back and selected one of the line segments.  :-)

wapperdude

@Yacine:  You do realize that page 3 looks like a swan floating on water?   ;)   8)

@Markem:  Now that you have all of these line segments stitched together, are you then going to apply some variable width algorithm?  ...and then, all the little branching tributaries?  Phew!  Lot of work!

Wapperdude
Visio 2019 Pro

markem

wrapperdude:  Actually - yes.    :D

I now have it doing variable width lines as I go along.  I'm going to have to do something (probably a dialog box) that will make it so I can select whether I want the line to just increase in size or if I want it to deviate along the path.  Here is the code so far:

Main Object(in the ThisDocument)
Dim myMouseListener As MouseListener
Dim btnLocations(1000, 1000) As Double
Dim btnCount As Integer

Public Sub DrawLine_Example()

    Dim vsoShape As Visio.Shape
   
    Set myMouseListener = New MouseListener
   
    Debug.Print "Ready"
   
End Sub


Class Module
Dim WithEvents vsoWindow As Visio.Window
Dim xc As Double
Dim yc As Double
Dim myButton As String
Dim btnLocations(1000, 1000) As Double
Dim btnCount As Long
Dim I As Long
Dim myWeight As Double
Dim myDir As Long

Private Sub Class_Initialize()

    Set vsoWindow = ActiveWindow
    btnCount = 0
    myButton = "LU"
    Math.Randomize
    myWeight = Math.Rnd * 0.01
    myDir = 1
   
End Sub

Private Sub Class_Terminate()

    Set vsoWindow = Nothing

End Sub

Private Sub vsoWindow_MouseDown(ByVal Button As Long, ByVal KeyButtonState As Long, ByVal x As Double, ByVal y As Double, CancelDefault As Boolean)
   
    If Button = 1 Then
        myButton = "LD"
        btnCount = 0
        btnLocations(btnCount, 0) = x
        btnLocations(btnCount, 1) = y
        Debug.Print "Left mouse button clicked"
    ElseIf Button = 2 Then
        myButton = "MD"
        Debug.Print "Right mouse button clicked"
    ElseIf Button = 16 Then
        myButton = "RD"
        Debug.Print "Center mouse button clicked"
    End If
       
End Sub

Private Sub vsoWindow_MouseMove(ByVal Button As Long, ByVal KeyButtonState As Long, ByVal x As Double, ByVal y As Double, CancelDefault As Boolean)
    Debug.Print "x-position is "; x
    Debug.Print "y-position is "; y
    If (myButton = "LD") Then
        btnCount = btnCount + 1
        If (btnCount > 1000) Then btnCount = 1000
        btnLocations(btnCount, 0) = x
        btnLocations(btnCount, 1) = y
        Set vsoShape = ActivePage.DrawLine(btnLocations(btnCount - 1, 0), btnLocations(btnCount - 1, 1), btnLocations(btnCount, 0), btnLocations(btnCount, 1))
        vsoShape.Cells("CenterX") = True
        vsoShape.Cells("CenterY") = True
Debug.Print "myWeight = "; myWeight
        If myWeight < 0.1 And myDir > 0 Then
            myWeight = myWeight + Math.Rnd * 0.001
            vsoShape.Cells("LineWeight").Formula = "=" & myWeight
            ElseIf myWeight > 0.01 And myDir < 1 Then
                myWeight = myWeight - Math.Rnd * 0.001
                vsoShape.Cells("LineWeight").Formula = "=" & myWeight
            ElseIf myWeight > 0.1 And myDir > 0 Then
                myDir = 0
                myWeight = myWeight - Math.Rnd * 0.001
                vsoShape.Cells("LineWeight").Formula = "=" & myWeight
            ElseIf myWeight < 0.01 And myDir < 1 Then
                myDir = 1
                myWeight = myWeight + Math.Rnd * 0.001
                vsoShape.Cells("LineWeight").Formula = "=" & myWeight
            End If
        End If
           
End Sub

Private Sub vsoWindow_MouseUp(ByVal Button As Long, ByVal KeyButtonState As Long, ByVal x As Double, ByVal y As Double, CancelDefault As Boolean)
   
    If Button = 1 Then
        myButton = "LU"
        Debug.Print "Left mouse button released"
    ElseIf Button = 2 Then
        myButton = "MU"
        Debug.Print "Right mouse button released"
    ElseIf Button = 16 Then
        myButton = "RU"
        Debug.Print "Center mouse button released"
    End If
       
    Set myMouseListener = Nothing
End Sub


Right now this does variable width along the line changing the lineweight as it goes.  I can modify it so it will just increase but this is pretty neat just by itself.  However, I might want the variation in size to be different.

Ya know - you say "That's a lot of work" but think of it like this - how much work is this going to save me?  Instead of trying for hours to get a river to look right I can adjust this simple program and make something really interesting. Cool....don't cha think?  8)