ThinkGeo.com    |     Documentation    |     Premium Support

Confusion over points & features

Is there anywhere that explains simply the principles of shapes & features & the differences between them?


For example, are the following 2 statements true?


1) Features can have labels but shapes cannot.


2) Shapes can be rotated & moved but features cannot.


Looking at example projects, whenever I see sample code for labels, it is associated with features, not shapes, but whenever I see sample code for moving & rotating, the code is associated with shapes, not features.


What I was originally trying to do was have a shape (a ship) which I could move & rotate & label, after reading the data from a SQL Server 2008 table (with no spatial data in it). I got all done apart from the labeling. It seemed I needed to be using features instead of shapes to get labeling done but that brought up problems of then not being able to move or rotate features....


I seem to spend more time trying to find examples than actually reading them. There are C# sample & VB samples to choose from, then if I find a VB sample it invariably is in VB.Net 2005 or something else old that VB.Net 2010 can't read because it has a vbproj file. I will certainly be looking forward to the day when we get a real user manual, even if it is in the form of a Wiki - trying to work from examples and an API document involves a huge learning curve.


Dave



I’m a customer, rather than support, but I might be able to help a little. 
  
 A shape is the actual geometry object that gets drawn.  A shape has no properties other than it’s geometry… whether a point, line, polygon, etc.   And, David would indicate that’s an oversimplification.   Actually, what gets drawn is binary data and the shape is a wrapper tha exposes that data in a way that is fairly standard in a GIS. 
  
 A feature is an object that contains a logical shape, along with a collection of other attributes.   Many of the drawing functions take a collection of features, and a related style may reference one or more attributes of the feature in order to determine visual presentation and label placement.    One can query a shape out of a feature, or construct a feature around a shape. 
  
 Think of a shape as the geometry part of a shapefile, and a feature as the equivalent row in the .dbf, with the shape embedded. 
  
 It is so incredibly easy create your own layers, deriving from the ThinkGeo layer, that we have become less and less dependent upon the native Feature classes.  It’s pretty easy to draw directly to the canvas or via a style within the DrawCore implementation of your own layer object.   If you have to do much work to construct a feature, you might be happiest just having your own class and draw/label things exactly the way you want from your own business objects. 
  
 We have objects that we want drawn rotated.  They are actually grids.   We have a single record defines the origin and rotation of the grid, as well as the cell size and number of rows and columns.   Each cell is divided into another grid.  Depending upon scale, we want to display only the grid boundary, the main cells, or the subcells.   We used to create a collection of features for each cell, and a collection of features that were the subcells.  But we had to do the math to generate them dynamically, anyway.   We ended up creating a derived layer and we just do the calculations dynamically in the draw core method.   It was much easier than trying to create features and build styles to turn them on and off and color and label them appropriately.     
  
 I guess it’s just what you get used, too, but we are a fan of rolling your own layers that wrap your native business objects. 


David, 
  
 I think Ted’s answer is very good, it’s better than my words, Thanks for your help, Ted. 
  
 In short, basically feature is shape + columnValues which is a dictionary of values represent column data related to this feature. 
  
 Please let me know if you have more questions about that.  
 Thanks 
 James

Guys, 
  
   If there is one thing I would change about our API it would be to merge the Feature and Shape.  It is the source of allot of confusion out there.  It’s funny because when I designed the feature and the shape I thought it was a very good idea and was a big improvement over Map Suite 2.0.  Here is a little history on how it came to be… 
  
   I the beginning, well Map Suite 1.0/2.0 more precisely, we only had shapes.  What I mean by shapes are high level classes like Polygon which is a class and has collections of things like inner rings which in turn has collections of smaller things like points.  Life was good, but slow…  The problem was that drawing was action the map did more than anything else and in drawing we read the binary data, convert it to a shape and then draw it.  We wanted to convert the raw data to a shape so that through our API it would be easy for our users to get the shapes and possibly manipulate them.  The problem was that for every drawing cycle the shapes were throw away, meaning after we drew them we no longer needed them.  This was a problem because each polygon was a big object and it had lots of little objects in it.  Drawing something like the world countries map would generate millions of classes and each of these had to be created and destroyed on the heap.  I imagine it drove the garbage collector nuts since the scope of the variables were well outside of one function which meant they could possibly be promoted to higher levels of the memory hierarchy. 
  
   The solution, I thought at the time, would be to create a very lightweight structure, the feature, that at its core would be well known binary.  This lightweight structure would be used in the main drawing cycle and always reside on the stack.  If you had lots of these features then they would be stored in an array and get even better memory packing and efficiency.  99% of the time you never actually have to touch the features as they are most commonly just drawn.  The problem with a feature, as it was a light weight structure, was that it was not specialized like the LineShape and PolygonShape etc so you could not do much with it exect draw it or convert it to a shape.  We wanted the shapes to be nice high level object with great intellisense and a rich straight forward API.  They were heavier than the feature but we thought the trade off was good.  It was easy, of course, to convert a feature to a shape and vice versa.  We also included overloads to take both shapes and features in nearly every API.  If you wanted to loop through the rings of a polygon and looks at its points then the shape was for you.  If you wanted raw performance then the feature was the way to go. 
  
   There was a rub though and as Ted pointed out when we draw we many times need more than just the geometry data, we need column data.  We had to tack on the ColumnValues to the feature and we did not do the same for the shape.  Looking ahead we might just do that and make sure when you convert to and from that data is preserved.  More than that the creation of the two brother classes created confusion.  Couple that with less than stellar documentation, being gracious, in the end it caused more harm than good.  We gained the performance, the shapes are nice and high level, but the end effect is that you feel like you are always getting one type when you need the other.  It just didn’t work out so well.  The other side effect was that average developer tend not to be very familiar in dealing with structures and their inherit differences with references types.  With the features you always get copies as you pass it around and this can cause some strange effects and even more confusion.  I get tripped up with it all the time especially when the feature is passed through an event’s arguments. 
  
   The better solution came to me when it was released and already too late, as it seems to always go.  I am not sure how we could shoe horn this in but I will explain the approach anyway.  What I would do now is to just have shapes however I would change their nature a bit.  I would add the ColumnValues to them so that they could be used in the drawing cycle.  The reason I would go this route is because of the Vertex structure.  In the 3.0+ model the shapes store their points as arrays of the Vertex structure.  This means that we have a slight overhead of a few classes per record but the vast amount of point data is in structure form on the stack and very effective to store and collect.  In hindsight we didn’t really need the feature and could have enhanced the shapes and made life easier for all.  I am sure I am forgetting some critical aspect of this but thats my thoughts for now.  The feature seemed like a good idea at the time and I apologize for saddling you all with it. :-( 
  
 David