Introduction
CanvasGIS is an object oriented 2D graphics drawing component. It's a part of MVisionTech open source GIS and data visualization framework. CanvasGIS had been used in the GisMap component presented in my previous article.
Many applications require two dimensional graphics to provide graphical input and represent different types of data. Some examples of two dimensional data presentation are charts displaying numerical data, maps representing the geometry of roads and other geographical objects, diagrams representing object relations and CAD/CAM tools. Canvas is an attempt to create a component that will serve them all.
There are some functionalities and requirements which are common among different types of graphical applications:
- Draw different kinds of shapes and manipulate them graphically.
- Navigate through geometrical data including zooming, pining and data layer selection.
- Changing presentation parameters such as colors, line styles etc.
- Assign different presentations of data for different scales, for example, when displaying maps in course resolution show only the main roads and country boundaries and when the user zooms in show the streets and other finer details.
- Creating several views of the same geometrical data.
- Perform graphical data manipulation, create new objects and maintain connection between presentation and the actual data. Create, edit and delete geometrical objects.
- Handle data coming in different coordinate systems. Perform data conversions between different coordinate systems.
- Create handles for different shape events. Events can be shape creation, editing, movement and deletion.

Layers, scales and graphics optimization
Dealing with large amounts of graphics requires special data structure and optimization. Consider the case where we want to display the roads in a country. When the user zooms out to see them all together, the map will be cluttered with lines (even for a small country) and these lines take a lot of time to draw. On the other hand, when the user zooms into the map to see one single block of streets it takes too much time to find out the lines that should be displayed (polygon clipping).
One of the ways of dealing with different detail levels (multiple resolutions) of data is to introduce graphical layers with different visibility in different scales. In the example below we create different graphic layers for the Earth's image and aerial photo of some city with a polygon outlining the border of a building.
The Earth's image is visible in a range between 0.1 and 0.5 (using layer min and max scale parameters).

Arial photo is in a range between 0.5 and 8, so when we zoom into the map it switches off the Earth's image and turns on the aerial photo. GisMap GIS component uses this functionality to switch between different resolutions of geographical data.

Of course, it's not feasible to have different layers for every possible resolution we need, so we use additional optimization techniques:
- Polygon simplification- There is no point in displaying things that we can't see, for example, we can't see deviations less than one pixel on the screen. So, as per the specific resolution we can approximate the original polygon to a simpler one with less points. The approach that we take is consecutive subdivision of a simple polygon (approximation) till the distance from the simple polygon to the original one (approximation error) is less than 1 pixel.
- Geometrical data structure- There are various data structures that are used to accelerate geometrical data, such as range trees, quadtrees etc. We currently use simple subdivision of graphical shapes of the grid with equal cell dimensions. Every cell in the grid contains references to the geometrical shapes included in the cell. So, when user zooms into certain area, all the cells included in the area are displayed.

Using the component
Canvas consists of two namespaces: CanvasControl and GeomModel. CanvasControl is a view in View/Model pattern and GeomModel is a model:
using GeomModel;
using CanvasControl;
In order to draw shapes on the canvas, one of the "create shape" methods can be used. For example, to draw a line:
canvas1.CreateLine();
Once the method has been called the canvas is transferred into the drawing state, so that the user can draw a shape. There are create methods for lines, rectangles and polygons, it can also be reused by other shapes, for example, ellipse can be derived from a rectangle:
EllipseCanvasItem ei = new EllipseCanvasItem(canvas1.CurrentLayer);
canvas1.setMode(CanvasControl.Canvas.DrawingMode.Rectangle);
canvas1.CreateShape(ei);
The shape can also be created directly on the canvas without user drawings:
ArrayList pi = new ArrayList();
pi.Add(new PointF(0,0));
pi.Add(new PointF(10,0));
pi.Add(new PointF(10,10));
pi.Add(new PointF(20,20));
PolygonCanvasItem pi = new PolygonCanvasItem(pi,canvas1.CurrentLayer);
canvas1.AddShape(pi);
Shapes in the canvas are organized in layers. The layers define the shape colors and the order in which the shapes are presented in the canvas. A new shape can also be created for a group of shapes:
GeomModel.CanvasLayer lay =
new GeomModel.CanvasLayer("new-layer",Color.Blue,0,true);
Different attributes can be assigned to the layer, such as line color, fill color, line width, and scale range from min to max where the group of shapes will be visible. The last feature is used in displaying geographical maps where each scale has different detail level.
Delegates can be assigned to the shapes to handle different events, for example, to handle the find shape event which occurs when the user clicks on the shape (canvas should in "find" mode):
this.canvas1.ItemFindEvent +=
new CanvasControl.Canvas.ItemEventHandler(this.canvas1_ItemFindEvent);
...
private void canvas1_ItemFindEvent(object sender,
GeomModel.ItemEventArgs e)
{
m_selected = e.indx;
propertyGrid1.SelectedObject = canvas1.GetItem(e.indx);
MessageBox.Show("Item:"+e.indx+"found");
}
Design
Canvas consists of two main classes Canvas and GeomModel implementing the Model/View design pattern:

Canvas is a view of the geometrical model (GeomModel) that holds the client to real world transformations between the view and the geometrical model. When the view is changed as a result of zoom, translation or resize, the canvas passes the request to the geometrical model to draw all the shapes visible in its view using the changed transformation.
GeomModel keeps all the shapes derived from the CanvasItem base class organized in layers. Several canvases can be attached to the same model. When the model changes all the canvases receive notifications and accordingly update there views (model/view design pattern).
CanvasLayer keeps the presentation attributes of a group of shapes.
CanvasItem is the base class for the shape presented in the canvas. New shapes can be added to the canvas by implementing the CanvasItem interface.
PolygonCanvasItem, PointCanvasItem, ImageCanvasItem etc. are different implementations of the CanvasItem interface.
| You must Sign In to use this message board. |
|
|
 |
|
 |
Hi, I downloaded the source code and tried to compile it with VS2005, but I couldn't.
Is there any source code for VS2005? Where can I find documentation about the component?
Thanks,
Michael.
|
| Sign In·View Thread·PermaLink | 1.50/5 |
|
|
|
 |
|
 |
I can partly compile it in VS2005 by adding the msvcmrtd.lib dependency. (thanks to Senthil)
Did you try adding msvcmrt.lib to the Additional Dependencies section?
Regards Senthil
Now, there is a missing file in the GdalImage module. Where can I get the gdal_priv.h file?
Thanks Nathalie
|
| Sign In·View Thread·PermaLink | 1.00/5 |
|
|
|
 |
|
 |
OK, I found the answer for the missing file on the other article.(http://www.codeproject.com/csharp/gismap.asp)
And I've been able to compile the CanvasDemo with this CanvasControl Project.
Nathalie
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Any suggestions for modifying the code so that this could work in a mobile application, say on Pocket PC 2003?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Sounds like a good idea, I don't have much of experience in it, but if you can do it I'll update original code.
Eduard.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
In the demonstrator package you have a Rotate function that seems intended to rotate by pi/4. Although there is some sort of rotation, it's certainly nothing that I can work out. In the Canvas code the line: curr_trans.Rotate((float)this.m_angle); would seem to be trying to do what is asked but for some reason it's not. I can't work out, for example, where the centre of rotation is supposed to be.
If you Move after doing a Rotation you get a funny trailing edge effect. I think the object finder is also confused after Rotation. I'm not yet sufficiently familiar with the code to see where these problems arise - but if the matrix transform is also confused, maybe that's the root cause.
Steve
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Thanks for the comment,
I'm going to fix it in the next release of the s/w, which I'm planned to release next month.
Eduard.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Great. The package is very impressive and I look forward to the new release.
There's one other thing I noticed and didn't try to track down. I had an idea of making the Canvas Transparent on top of another object. But if you move an object over the Canvas it doesn't clean up after itself. Maybe this is a wrong use for Transparent, so if it is, please ignore this comment.
Good luck with the upgrade.
Steve
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
The binary package works fine. The source package seems to be very similar to the GIS package and does not seem to be the standalone demonstrator of the Drawing component. I still can't get the package to compile (see our discussions in the GIS component page) as it still insists that GdalImage.dll components aren't there, even when I make sure that they are. But as I seem to be the only one with that problem it must be my fault.
Steve
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Steve, Sorry for the hard time you have with this package.
I download it by my self, but it seems to work in my computer. It complans on missing source control at the beginning but then works fine.
You are right, source package is similare to the GisMap one, the difference is that CanvasPainter is set as an active project.
For this particulare project you don't need most of dlls (projects), you need only: CanvasPainter,CanvasControl and Geometry, so you can delete the rest.
It looks like you are having problems with C++ dlls, you can go to GdalImage project and build it separatly, it can help.
What version of VisualStudio you have? I'm using VS 2003 and .NET framework 1.1.
Eduard.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I got the Canvas project to work with your 'delete' suggestions.
It might be still be useful if you could repackage the Canvas demonstrator without all the GIS stuff. I deleted the obviously irrelevant stuff, but there were still a few more GIS things hidden in the project (such as a GIS element on the Toolbar) that had to be deleted or remmed out. It would help naive new users such as myself to deliver a 'clean' package so they can concentrate on all the good stuff you provide.
Going back to the GIS stuff. I'm under VS2003 and 1.1 so the problems aren't there. When I tried to compile GdalImage as a stand-alone project I got an error: fatal error C1083: Cannot open include file: 'gdal_priv.h': No such file or directory
Maybe that's the problem.
Thanks for your help!
Steve
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
You are right Steve,
I took the same package I used for my previous article "GisMap"
This package depends on GDAL library version 1.2.0. You can download it at http://www.gdal.org/dl/gdal120.zip.
I'm going to repackage it in the next version.
Thanks, Eduard.
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
|