|
Subject:
|
Graphics
|
|
Posted By:
|
scruffyduck
|
Post Date:
|
5/22/2006 5:28:36 AM
|
So far in my programming 'career' I have managed to avoid graphics. Mostly because I have not needed it but also because it is an alien area to me. Now I need to do something and would appreciated any pointers on how/where to start. I am sure this has been done many many times before 
The specification outline is
I have a series of objects - each of which is a rectangle described in terms of it's type, placement point, width, length and heading (i.e. the angle at which is is placed). The co-ordinate system is latitude ( +90 to -90) and longitude (+180 to -180), width and length are described in meters.
I want to be able first to draw these objects onto a space so that their size and relationships are accurately represented.
I want to be able to zoom in and out on the objects and re center the visible area on different objects
I want to be able to select and object and bring up a window describing the object.
That is the first level I want to get to
Later I would like to be able to move the object by drag and drop, and rotate it about it's placement point. I do NOT resize it. I would then like to be able to add new objects into the area.
All pointers gratefully received
Jon Masterson
|
|
Reply By:
|
Rod Stephens
|
Reply Date:
|
5/26/2006 8:31:44 AM
|
First note that your coordinates span the entire globe which is a sphere not a rectangle so if you simply map this data to a rectangle you'll get deformed data similar to what you see on a flat map of the world. There are projection methods that map patches from spherical coordinates onto a flat surface but I havn't done that. You'll need to look around some cartography Web sites for those sorts of algorithms.
The Graphics object supports transformations that can represent translation, scaling, and rotation. The trick is to figure out hwo to translate and scale so your data appears where you want it. Here's a subroutine that sets the transformation for a Graphics object to map data coordinates with corners at (data_ul_x, data_ul_y)-(data_lr_x, data_lr_y) to the device coordinates (dev_ul_x, dev_ul_y)-(dev_lr_x, data_lr_y).
Private Sub ScaleControl(ByVal gr As Graphics, _ ByVal data_ul_x As Single, ByVal data_ul_y As Single, _ ByVal data_lr_x As Single, ByVal data_lr_y As Single, _ ByVal dev_ul_x As Single, ByVal dev_ul_y As Single, _ ByVal dev_ll_x As Single, ByVal dev_ll_y As Single) ' Start from scratch. gr.ResetTransform()
' Move (data_ul_x, data_ul_y) to the origin. gr.TranslateTransform(-data_ul_x, -data_ul_y, _ MatrixOrder.Append)
' Scale so the data rectangle's width and height ' match those of the device rectangle. gr.ScaleTransform( _ (dev_ll_x - dev_ul_x) / (data_lr_x - data_ul_x), _ (dev_ll_y - dev_ul_y) / (data_lr_y - data_ul_y), _ MatrixOrder.Append)
' Move the origin to (dev_ul_x, dev_ul_y). gr.TranslateTransform(dev_ul_x, dev_ul_y, _ MatrixOrder.Append) End Sub
For your example, the data coordinates would be the lat and long of the area you want to display. The device coordinates would be the corners of the PictureBox or whatever control you are drawing on.
You should pick the data bounds so the area's width/height ratio is the same as the control's width/height ratio so the data isn't stretched or squashed.
Rotating objects is not much harder than all this. The idea is: translate the object's center of rotation (for example, you might rotate around its middle) to the origin, rotate it, and then translate the origin back to the original center of rotation. So to draw a map with a rotated object:
1. Use ScaleControl to set up the map's basic transformation. 2. Draw the stuff that doesn't need rotation. 3. Save the transformation. I think you can store the Graphics object's Transform property. Or there's a method that essentially makes a checkpoint that you can later return to. 4. For each object that needs rotation: A. Add a translation to move the center of rotation to the origin. B. Add a rotation. C. Add the inverse of the translation for step 4A. D. Draw the object. E. Restore the transformation you saved in step 3.
Each step isn't too complicated but taken all together it can be pretty confusing.
I hope that helps.
Rod RodStephens@vb-helper.com Author of "Visual Basic 2005 Programmer's Reference" http://www.vb-helper.com/vb_prog_ref.htm
|
|
Reply By:
|
scruffyduck
|
Reply Date:
|
5/26/2006 11:10:05 AM
|
Thanks Rod
That is a big help plus I have re-read the section on Graphics in the book. And yes I am finding it confusing in totality so I will need to build it up bit by bit like a prototype .
I do have the algorithms for spherical geometry since my program uses them to calculate distance and bearing between two points and also I can determine the co-ordinates of a far point based on bearing and distance. The actual area over which the program needs to operate is small (normally no more than 3000 meters square) but it can be anywhere on the earth.
I am wondering if I would do better to turn everything from latitude and longitude into x & y distances in meters from a reference point before I start. My program can do that as well taking sherical geometry into account.
Jon Masterson
|
|
Reply By:
|
Rod Stephens
|
Reply Date:
|
5/27/2006 7:24:52 AM
|
Hi Jon,
Yes, it might be best to convert into x & y so you have a flat coordinate system to draw from. Otherwise things get really weird near the poles. Imagine plotting the North Pole in the center of the form and then being faced with several points that all have latitude < 90. You'd need to make the conversion at that point anyway.
Rod RodStephens@vb-helper.com Author of "Visual Basic 2005 Programmer's Reference" http://www.vb-helper.com/vb_prog_ref.htm
Sign up for the free VB Helper Newsletters at http://www.vb-helper.com/newsletter.html
|
|
Reply By:
|
scruffyduck
|
Reply Date:
|
5/27/2006 7:41:25 AM
|
I'll keep you posted how I get on or not as the case maybe 
Jon Masterson
|
|
Reply By:
|
scruffyduck
|
Reply Date:
|
5/29/2006 7:31:39 AM
|
OK I thought I might be seeing how some of this works but I am clearly not. Here were my working premises
1) the graphics object stores information about objects in world co-ordinates so it represents a big flat area and anything placed on it actually stays where it is.
2) the display area (for want of a better word) is the bit you can see - for example my picturebox.
Now what I was hoping was that I could set up a graphics object and populate an array with my rectangles - each is a class with it's size and the ability to draw itself (a draw method). For a test I set up a randomizer to create 25 rectangles of varying sizes and placed them using co-ordinates which could be bigger than my picturebox (I have not fiddled with units so I assume everything is in pixels). I can use a button to generate a random set of boxes, and invalidate the picturebox so they get drawn again. This works and I get random boxes drawn, but just those that fit into the picturebox co-ordinates
Now what I want to do is use navigation buttons to move the window(picturebox) around the graphics object by using translateTransform. OK so I think my simplistic view of things is falling apart here - I guess that actually the size of my graphics object (since it is taken from the picturebox is only the size of the picture box. I have a couple more buttons which I was hoping to use to zoom in and out using the scaleTransform but.......
Am I anywhere near the right track - do I need to create some other sort of graphics object to contain my boxes or am I only going to be able to draw what fits in the pictureBox? I have started to read about graphicContainers and that you can do scaling etc in them, but again I am not sure if that is correct.
Thank you for your patience 
Jon Masterson
|
|
Reply By:
|
Rod Stephens
|
Reply Date:
|
5/30/2006 7:59:09 AM
|
I think you're headed in the right direction. Use the Graphics object's TranslateTransform and ScaleTransform methods to resize and move the world coordinates. For example, this pseudocode scales by a factor of 2 (enlarges):
gr.ScaleTransform(2, 2, Append)
This one translates so things are drawn shifted 100 units to the right:
gr.TranslateTransform(100, 0)
This example may help:
http://www.vb-helper.com/howto_net_set_scale.html
Rod RodStephens@vb-helper.com Author of "Visual Basic 2005 Programmer's Reference" http://www.vb-helper.com/vb_prog_ref.htm
Sign up for the free VB Helper Newsletters at http://www.vb-helper.com/newsletter.html
|
|
Reply By:
|
scruffyduck
|
Reply Date:
|
5/30/2006 11:08:08 PM
|
Thanks Rod
I have the scaling and scrolling working now - seems to be quite simple once you know how I am now moving on to being able to click on a rectangle and select it to bring up information about the object it represents
Jon Masterson
|
|
Reply By:
|
Rod Stephens
|
Reply Date:
|
5/31/2006 7:30:58 AM
|
Ah, there's a trick to that, too. The Click and other mouse event handlers give you coordinates in the PictureBox's normal coordinate system. So if you have scaled by a factor of 2, the coordinates you get don't match those on the drawing.
To convert from screen to world coordinates, perform the inverse transformations in reverse order. For example, suppose to draw you used a translation by (-100, 50) and then a scaling of (2, 2). To map the mouse points to world coordinates, scale by (1/2, 1/2) and then translate by (100, -50). Use the Matrix class to perform the transformation.
See this example:
http://www.vb-helper.com/howto_net_set_invert_scale.html
Rod RodStephens@vb-helper.com Author of "Visual Basic 2005 Programmer's Reference" http://www.vb-helper.com/vb_prog_ref.htm
Sign up for the free VB Helper Newsletters at http://www.vb-helper.com/newsletter.html
|
|
Reply By:
|
scruffyduck
|
Reply Date:
|
5/31/2006 8:25:27 AM
|
Thanks Rod, I will try that out 
Jon Masterson
|
|
Reply By:
|
geofran80
|
Reply Date:
|
7/22/2008 2:23:58 PM
|
Dear friends, I'd like to create a geographic canvas from a form or picturebox as Jon Masterson.
If Rod or Jon, can contact to me to tell my anything about this.
I have a reader of geometry class and I need to show in the canvas in real mercator (metric) coordinates, or Lat/Lon coordinates.
How can I do to show this?
Thanks for advanced.
Francisco J. GIS Analyst and Developer. gistdt05@hotmail.com
|
|
Reply By:
|
Rod Stephens
|
Reply Date:
|
7/22/2008 2:43:41 PM
|
It depends on what your geometry class is and what the reader does. What kind of data does it load? Point and line data? Topography?
I'm not sure exactly what you need to do. If you need to draw points, lines, etc. that you loaded from the file, you can use the Graphics object's transformation methods to make this a little easier. Lat/Long will be easiest, although remember there will be some deformation over long distances.
If you look over the previous posts in this thread, it may help with the scaling.
Rod
Rod Stephens, Visual Basic MVP
Visual Basic 2008 Programmer's Reference http://www.amazon.com/exec/obidos/ASIN/0470182628/vbhelper/
|
|
Reply By:
|
geofran80
|
Reply Date:
|
7/22/2008 3:48:41 PM
|
Thanks Rod,
I have to load Points, Lines and Polygons shapes, I have some files as Shapefile (standard for Geographic Information Systems - ESRI) and another files simmilar to CAD.
I thought that it would be more useful to load the data in metric coordinates (as Mecartor or another projection) because the units was more convertible to metric not angular (Lat/Lon).
If I have a file as the following (in ASCII, TXT or CSV format)
IDPoint, XCoordPoint, YCoordPoint 1, 450342.25, 7438278.10 2, 530724.27, 7349827.11 . . . 25, 127832.21, 7872827.45
These coordinates are in meters from the origin x (greendwich meridiam) and origin y (ecuator paralel)
If i want to load that file that would show all points in the canvas, how can I do to translate or scale the canvas conform I add new points and show in real coordinates if the canvas or picture, form, and so is shown in pixel units?
Thanks for a lot of.
Francisco J. GIS Analyst and Developer gistdt05@hotmail.com
|
|
Reply By:
|
Rod Stephens
|
Reply Date:
|
7/23/2008 9:55:00 AM
|
You should probably use the Graphics object's transformation methods to define a scale so you can plot the points in their native coordinates. The object will automatically scale them appropriately.
If you really want to learn where the transformed points are, you can use the object's properties to get its transform matrix and apply it to the points. Or you could write your own transformation. But those seem like a lot of work.
Rod
Rod Stephens, Visual Basic MVP
Visual Basic 2008 Programmer's Reference http://www.amazon.com/exec/obidos/ASIN/0470182628/vbhelper/
|
|
Reply By:
|
geofran80
|
Reply Date:
|
7/23/2008 11:21:15 AM
|
Many thanks Rod,
I will try it.
I have transformation methods to convert in UTM (projected coordinates) the Lat/Lon values of points, but i didn't know how can I do to translate/scale my canvas.
I will try it and comment my results here.
Thanks.
Francisco J. GIS Analyst and Developer. gistdt05@hotmail.com
Francisco J. GIS Developer
|