ThinkGeo.com    |     Documentation    |     Premium Support

Rotated Points and Text

I know that I have seen posts related to these topics, but I haven't found a solution yet.  I need to place Lables and Point Symbols at an angle.  The angle for each point symbol and label can be different, so setting an angle for a layer won't work.  I also need to place a particular symbol based on a value stored in the database.  I can create the symbol shape on the fly, but I need to know how to override the point and label drawing operation to place exactly what I want, where I want , oriented the way I want.  Does anyone have any sample code showing how to do this?  Finally, is it possible to specify the font used for a label and is it possible to use True Type fonts for labels?



Charles, 
  
 You can create your own RotatePointStyle by inheriting the existing PointStyle, in the protected DrawCore method, you can rotate and render each feature differently with your own logic. In this way you only need one layer and still you can rotate every point with different angle. 
  
 Thanks, 
 ThinkGeo Support 


I wouild like to ask again along with Charles for some working sample code.


I need all the same features described by Charles and assume anyone else intending to use Thinkgeo to do asset tracking is going to require some of the same features. Without these capabilities my project is probably a no-go. 


I also am asking for source because I spent several days experimenting with the rotate method just to find out it doesn't work.


Below is just some of the test code that doesn't work. I will note I haven't even gotten close to trying to label the points.


 


        Dim ps As New PointShape()
        'ps = BaseShape.Rotate(ps, ps, 90) 'this doesn't work
        ps.Id = "1"
        ps.Rotate(ps, 90)
        ps.X = xpos
        ps.Y = ypos
        If ps.CanRotate Then 'this does evaluate to true
            ps.Rotate(ps, 90) 'this doesn't work
        End If


        Dim DynamicVehicleLayer As InMemoryFeatureLayer = DirectCast(Map1.FindFeatureLayer("BitmapLayer"), InMemoryFeatureLayer)

        DynamicVehicleLayer.Open()
        DynamicVehicleLayer.EditTools.BeginTransaction()
        'bml.EditTools.Rotate("1", ps, 20)' this doesn't work
        DynamicVehicleLayer.EditTools.Update(ps)
        DynamicVehicleLayer.EditTools.CommitTransaction()
        DynamicVehicleLayer.Close()

        'all proterties of the pointe shape are updated except the rotate

        Map1.RefreshDynamic()



Alan & Charles,


Below is the sample:





public class RotatePointStyle : PointStyle
{
    public RotatePointStyle()
        : base()
    { }

    protected override Collection<string> GetRequiredColumnNamesCore()
    {
        Collection<string> columns = new Collection<string>();
        columns.Add("Angle");
        columns.Add("VehicleImage");

        return columns;
    }

    protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, Collection<SimpleCandidate> labelsInThisLayer, Collection<SimpleCandidate> labelsInAllLayers)
    {
        foreach (Feature feature in features)
        {
            int angle = Convert.ToInt32(feature.ColumnValues["Angle"]);
            string vehicleImagePath = feature.ColumnValues["VehicleImage"];
            PointShape location = (PointShape)feature.GetShape();
            canvas.DrawWorldImageWithoutScaling(new GeoImage(vehicleImagePath),location.X, location.Y, DrawingLevel.LevelFour, 0, 0, angle);
        }
    }
}

Your code like this:




InMemoryFeatureLayer inMemoryLayer = new InMemoryFeatureLayer();
inMemoryLayer.Columns.Add(new FeatureSourceColumn("Angle"));
inMemoryLayer.Columns.Add(new FeatureSourceColumn("VehicleImage"));
inMemoryLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
inMemoryLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(new RotatePointStyle());

Feature feature1 = new Feature(new PointShape(0, 0));
feature1.ColumnValues.Add("Angle", "45");
feature1.ColumnValues.Add("VehicleImage", @"C:\image\Car.png");
inMemoryLayer.InternalFeatures.Add(feature1);

Feature feature2 = new Feature(new PointShape(104, 30));
feature2.ColumnValues.Add("Angle", "180");
feature2.ColumnValues.Add("VehicleImage", @"C:\image\Car.png");
inMemoryLayer.InternalFeatures.Add(feature2);

winformsMap1.DynamicOverlay.Layers.Add(inMemoryLayer);
winformsMap1.RefreshDynamic ();

 


Hope it helps.


ThinkGeo Support



Thanks for the sample code.  I remembered the extending MapSuite webinar almost as soon as I posted the question.  I retrieved the sample code for that, but this code answers a question about using its sample code with the winformMaps control (sample used a PictureBox control). 
  
 I still have a question about point shapes.  What exactly can be used as a point shape.? Obviously, image files of at least the PNG type can be used.  Can it be other image file types?  Does it have to be an image?  Could it be a shape from an SQL Server Spatial database?  This is not really a problem either way, I just want to understand any limitations I am under. 
  
 I still need to know about rotated text and fonts.

Charles,


You can use image, character and symbol to draw in PointStyle by changing the property pointStyle.PointType.


For using image, we support BMP, JPG, GIF, PNG and TIF for now, you need to set the property pointStyle.Image besides set the PointType to PointType.Image.


Also you can use the predefined PointSymbolType like Star, Diamond, and Circle etc by specifying the PointType.Symbol.


If you want to use some other like geometry from SQL to represent a point, you can do that by writing your own PointStyle. Below is a presentation on how to create your own custom styles.

gis.thinkgeo.com/Support/Dis...fault.aspx


Thanks,

ThinkGeo Support

 



 


Charles,
 
I am afraid the code I provide above just shows how to rotate the image but missed the text part. I added some extra code and created a sample attached showing how to make the symbol and text in different angle. You will also find a way how to specify the font in the sample.
 
Thanks,
ThinkGeo Support 

674-5698.zip (11.3 KB)

I tried running the above 5698.zip sample but get the following error using Desktop Edition 3.0.0.0 (that is what the VB.Net Properties say though I suspect it is wrong - it is the last version before 4.0 as we only just purchased recently. Also VB.Net says the Runtime Version is v2.0.50727 if that is any use): 



Error 3 'ThinkGeo.MapSuite.DesktopEdition.WinformsMap' does not contain a definition for 'DynamicOverlay' and no extension method 'DynamicOverlay' accepting a first argument of type 'ThinkGeo.MapSuite.DesktopEdition.WinformsMap' could be found (are you missing a using directive or an assembly reference?) C:\Documents and Settings\David\My Documents\Visual Studio Projects\ThinkGeo\5698 Post\Demo\Form1.cs 42 26 Demo 



in this line: 



winformsMap1.DynamicOverlay.Layers.Add(inMemoryLayer); 



Have their been some changes since that sample was released that make the sample not work any more? 



2 warnings also show, saying: 



Warning 1 'ThinkGeo.MapSuite.Core.InMemoryFeatureLayer.InternalFeatures' is obsolete: 'You are bypassing the automatic spatial indexing if the modify, add or delete. You need to call BuildIndex method later.' C:\Documents and Settings\David\My Documents\Visual Studio Projects\ThinkGeo\5698 Post\Demo\Form1.cs 33 13 Demo 



so I am guessing this might need to be revisited to get it working again. 



Sorry that I am not much more help, but I don't use C# myself but can usually look at the C# code and understand enough to figure out how to do it in VB.Net.



David,


Thanks for your post and questions; this post is an old thread nowJ.
 
We did some change from its Release candidate, I updated the sample in latest version of Desktop Edition, please take a try and feel free to let me know if any problems.
 
Thanks.
 
Yale

Post5698.zip (11.7 KB)

Yes, that works fine with my MapSuiteCore:3.1.299;DesktopEdition:3.1.299 and is quite useful. 



One question: I see that the features have certain characteristics embedded in columns like this: 

feature1.ColumnValues.Add("ImageAngle", "0"); 

feature2.ColumnValues.Add("ImageAngle", "45"); 



Once the objects are drawn, is there a simple way to change the values in the column? Something like: 

feature1.ColumnValues.Change("ImageAngle", "0"); 

feature2.ColumnValues.Change("ImageAngle", "47"); 

and then do a refresh to have all the vehicles change rotation (and also position in my final plan)? 



I am playing with it now to just add a simple button to have the 2 vehicles change rotation to a random angle when the button is pushed. There isn't a ColumnValues.Change method that I can see. Still hunting around....



David, 
  
   I don’t have VS in front of me but i can point you in the right direction though the exact API might be a bit off.  If you want to change on of the values you need to query it back from the InMemoryFeatureLayer.  The code would look something like below… 
  
 // The InternalFeatures is a shortcut directly into the storage area of the InMemoryFeatureLayer.  It is a bit of a hack but fast, the proper way is the  
 // next sample.  NOTE: If you change the position using this method you need to call the InMemoryFeatureLayer.BuildIndex.  This creates an in 
 //memory index, if you use the transaction system it is automatic. 
  
 Feature feature = inMemoryFeatureLayer.InternalFeatures(“feature id”); 
 feature.ColumnValues[“RotationAngle”] = “100”; 
  
 Or you can go through the edit system…  If you want to go through that way it would be something like… (I might get this wrong…) 
  
 // Get the feature 
 Feature feature = inMemeoryLayer.QueryTools.GetFeaturebyId(“feature id”, ReturningColumns.ReturnAllColumns); 
 //Modify the feature 
 feature.ColumnValues[“Rotation”] = “100”; 
 // Use the edit system to commit it back.  Of course if you updated many items you can do it all in one transaction 
 inMemoryFeatureLayer.EditTools.BeginTransaction(); 
 inMemoryFeatureLayer.EditTools.Update(feature); 
 inMemoryFeatureLayer.EditTools.CommitTransaction(); 
  
 There is no chance of this compiling but I hope you get the idea.  Sorry but I wanted to get you something soon…  If you can’t get this to work let us now and we can officially modify the sample. 
  
 David