ThinkGeo.com    |     Documentation    |     Premium Support

Scaling Point Style

 I read with interest the article in the Developer Blog on "Writing a Scaling Image Style". That got me inspired and I want to create my own inherited class for drawing Capitals in a way comparable to the class ScalingImageStyle2.


  I am running into difficulties in the Protected Override DrawCore function where I want to draw the point features as little squares as does PointStyles.Capital1.


 I see that canvas as GeoCanvas is passed to draw on but I was expecting something like the graphics object of GDI+ where I can easily draw shapes as I want. In my case, I want to draw a litle square inside a bigger one as in PointStyles.Capital1 but I don't find a method for that in GeoCanvas.


Let say, to keep things simple, that I want to draw a square of the size of 10 in that DrawCore function that I override.  I can see DrawEllipse in GeoCanvas but I don't see any thing for drawing a Square as I want. How do I do that?


 


 



Adolfo, 
  
   I have a little trick to share with you that will make your life easier.  If inside the style’s DrawCore you want to draw a square like you mentioned you only need to do the following.  Instantiate an new PointSytle in the method, set its parameters for how you want it to draw.  Next call the Draw method on it and pass all of the parameters that were passed into you on the DrawCore like the canvas, etc.   As this shows you can stack style inside of each other so there is no need to re-invent the wheel. :-)  Using this method you can quickly wire up pieces and parts together into something truly cool! 
  
   On the GeoCanvas the idea was to have it draw like GDI+'s Graphics object but to draw Features.  The idea is that user typically have Features and this allows us to write all the hairy code to convert a Feature in world coordinates to a screen shape for GDI+.  This is the main scenarios however it does complicate your situation but I hope you find the trick above useful.  I will add a task in our issue tracking system to possibly add some simple drawing objects to make this easier in the future. 
  
 David

Thank you David. With your tip, I have the Scaling Symbol class exactely as I wanted. Now that I know the Draw method of Style exists and I understand how to use it, I could write the appropriate code in the Override DrawCore method. See my new class:


 




public class ScalingCapitalStyle : Style
        {
          
            private GeographyUnit mapUnit;
            private double maximumScale;
            private double minimumScale;
            private double maximumSize;
            private double minimumSize;
            private float xOffsetInPixel;
            private float yOffsetInPixel;
            

            // A default constructor that just calls the main constructor
            public ScalingCapitalStyle()
                : this(GeographyUnit.DecimalDegree, double.MaxValue, 0, 20, 10)
            {
            }

            // A constructor with fewer parameters that calls the main constructor
            public ScalingCapitalStyle(GeographyUnit mapUnit,  double MaximumScale, double MinimumScale, double MaximumSize, double MinimumSize)
            {
               
                this.maximumScale = MaximumScale;
                this.minimumScale = MinimumScale;
                this.maximumSize = MaximumSize;
                this.minimumSize = MinimumSize;
                this.mapUnit = mapUnit;
            }



            // This is the map unit to determine the scale.
            public GeographyUnit MapUnit
            {
                get { return mapUnit; }
                set { mapUnit = value; }
            }

          

            // The maximum scale will be the largest scale used to calculate the size of the image.
            // If the scale gets larger than the max then we compute the scaling based on
            // this number instead.  This is mean that after this scale the image will not get
            // any smaller no matter how much more you zoom out.
            public double MaximumScale
            {
                get { return maximumScale; }
                set { maximumScale = value; }
            }

            // The minimum scale will be the smallest scale used to calculate the size of the image.
            // If the scale gets smaller than the min then we compute the scaling based on
            // this number instead.  This is mean that after this scale the image will not get
            // any larger no matter how much more you zoom in.
            public double MinimumScale
            {
                get { return minimumScale; }
                set { minimumScale = value; }
            }

            // The MaximumSize is the size of the image at MinimumScale and lower.
            public double MaximumSize
            {
                get { return maximumSize; }
                set { maximumSize = value; }
            }

            // The MinimumSize is the size of the image at MaximumScale and higher.
            public double MinimumSize
            {
                get { return minimumSize; }
                set { minimumSize = value; }
            }

            // This is the X offset in pixels for the image.
            public float XOffsetInPixel
            {
                get { return xOffsetInPixel; }
                set { xOffsetInPixel = value; }
            }

            // This is the Y offset in pixels for the image.
            public float YOffsetInPixel
            {
                get { return yOffsetInPixel; }
                set { yOffsetInPixel = value; }
            }


            // This is the method we needed to override.
            protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, System.Collections.ObjectModel.Collection<SimpleCandidate> labelsInThisLayer, System.Collections.ObjectModel.Collection<SimpleCandidate> labelsInAllLayers)
            {
                           double currentScale = ExtentHelper.GetScale(canvas.CurrentWorldExtent, canvas.Width, mapUnit);

                            // Enforce the minimum and maximum scale properties
                            if (currentScale > maximumScale) { currentScale = maximumScale; }
                            if (currentScale < minimumScale) { currentScale = minimumScale; }

                            int PointSize = (int)(maximumSize - ((currentScale - minimumScale) * (maximumSize - minimumSize)) /
                                                (maximumScale - minimumScale));
                            int PointSize2 = (int)(PointSize * 0.9);
                            int PointSize3 = (int)(PointSize * 0.6);

                            PointStyle pointStyle1 = new PointStyle(PointSymbolType.Square, new GeoSolidBrush(GeoColor.StandardColors.Black), PointSize);
                            PointStyle pointStyle2 = new PointStyle(PointSymbolType.Square, new GeoSolidBrush(GeoColor.StandardColors.White), PointSize2);
                            PointStyle pointStyle3 = new PointStyle(PointSymbolType.Square, new GeoSolidBrush(GeoColor.StandardColors.Black), PointSize3);
                
                            pointStyle1.Draw(features, canvas, labelsInThisLayer, labelsInAllLayers);
                            pointStyle2.Draw(features, canvas, labelsInThisLayer, labelsInAllLayers);
                            pointStyle3.Draw(features, canvas, labelsInThisLayer, labelsInAllLayers);
                }
        }



Adolfo, 
  
   Excellent!  The class looks good.  I really get excited when people extend our framework to elegantly accomplish things we never imagined when we built the classes.  I think what holds many developers back is not having a good understanding of how to extend classes and what abstract and virtual means.  This and not having a user manual, which we are working on!  I know before I started with ThinkGeo I didn’t and I had been programming many many years.  I think for most developers they never get a chance because they are always building high level apps that seldom require knowing about it.  You have inspired me to write a new white paper on how in general to extend our classes and some more tips on our object model. 
  
 Thank for the inspiration! 
  
 David