ThinkGeo.com    |     Documentation    |     Premium Support

Building complex line styles?

I asked this question in another thread, but apperently it's been overlooked:


How can I define a new custom line style that  incorporates complex styling on top of each other ? E.g. one that shows  symbols (like circles) at certain distances along a vector, left and right of the mid  vector ?


I've looked at utilizing  New LineStyle(New GeoPen(new GeoBrush(...))),  but it looks like the GeoBrush class isn't included in the  ThinkGeo.MapSuite.Core namespace, even though - according to the  documentation - it ought to be there !??


Are the any samples on how to utilize GeoBrush in construction of complex LineStyle's ?


TIA


 



I'm attaching a DOCX that shows the range of line styles I want to mimic.


 



MapInfo_pen_styles.docx (93.7 KB)

Lars I.


 I am sorry that your question has been overlooked in another thread. Can you point out to us that thread? We take our Discussion Forum very seriously and we want to make sure that does not happen again.


 I looked at your attached document ( I inserted a screen shot of it to make it immediatly visible to all the readers) and before we give you the exact answer, I would need you to specify a few things.


-In the custom line style that you want to create, the distances between the symbols are expected to be in screen coordinates or in world coordinates?


-When you say "left and right of a mid vector", do you mean displaying a symbol at mid distance of a line segment to the left or right according to its direction?


 I am asking those questions because it might be that in your case using a GeoBrush might not be the best approach. We have a few samples in the Code Community that show how to construct custom LineStyles for specific needs. If you go to the "Styles" category, you will see them wiki.thinkgeo.com/wiki/Map_Suite_We...es_Samples. For example, we have two samples that might be pretty close to what you are looking for:


There is Displaying One-Way Streets that shows how display an arrow at mid distance of a line segment. The direction of the arrow shows that there is a left and right concept.


There is Distance Line Style that shows how to display at mid distance the length of each line segment making up the LineShape.


There is Line Style With Increment that shows how to display at a constant world distance (ex meters) little bars. You can see that any other symbols could be used.


There is Start End LineStyle that shows how to display each LineShape with the start and end vertices with a differentiated symbol.


 In all those examples, the LineStyle has been inherited with the override DrawCore handling the custom drawing. Please, give us a few more information about your needs and I think we can provide you the exact custom LineStyle you need. Thank you.




Hi Val,


Thanks for your reply. The old thread if of no concern if you can help me out in this :-)


I have looked at the samples, especially the "Line Style With Increment", which looks interesting indeed. But the other samples are too simple for what I'm trying to accomplish.


The line styles I'm trying to mimic are in screen coordinates, and it's especially line styles 81 - 83 I'm currently looking at, but handling the rest of line styles will be relevant soon enough.


I've tried using a GeoTextureBrush() approach, but the tiled images are unfortunately tiled parallel to the window, and not the line direction, so it doesn't do the job.


As for "left" and "right", have a look at e.g. line style # 116. It has half-circles and rectangles positioned at regular intervals along the vector, all on the left side (the line styles are depicted going from left to right). How is such a thing accomplished in Map Suite ?


Do I need to draw these symbols "manually" in the custom line style class's DrawCore, using the "GetPointOnALine" method with screen coordinates ? A sample of building e.g. custom line style # 116 would be most helpful.


I've also looked for an in-depth description of how innerPen, outerPen, and centerPen works together, but haven't found it yet. Is such a description available ?


 



Hi again,


As for the inner/outer/center pens, I do have this description:


"You can set an inner, outer and center pen to give you a nice effect.  The outer pen draws first, and should typically be black and larger then  the inner pen. The inner pen draws next, and should be set as the color  of the road you want. It should be thinner than the outer pen. The  center pen draws last, and is used to represent a centerline in the  road. ..."


Does this mean that the only difference between the three pens is the drawing order ?


 



Lars, 
  
  I started working this afternoon on the example 116 of line according to the explanation you gave and I should have something ready to show you that will meet your requirements. It will also help to extent to the other examples.  
  
 Regarding the inner/outer/center pens, you are right, the only difference of the three pens is the drawing order but that allows you have some effects for drawing various types of symbols for roads for example.  
  
 I will send you the code and a screen shot showing the resuts for line 116 tomorrow. Thank you.

Hi Val, 



Wow, that's awesome ! 



I'll wait excitedly to see what you come up with :-) 



Thanks again



Hi Val, 
  
 I’ve now actually hand-coded style classes for two of the 100+ complex styles in question. 
  
 But I’m still a novice doing this, so I’m still excited to see what you come up with :-) 


Lars,


 I created a custom class for line style 116. In this example, it set the distance between the triangles on the line every 30 pixels and this distance stays the same as you zoom in or out. Notice that the triangles change angle according to the inclination of the line (which is the affect we want, I think). You will see in the DrawCore function of the class CustomLineStyle116 that I am using the regular PointStyle of type triangle. To have the exact effect as on your example where the base of the triangle is exactely on the line, a custom PointStyle class for drawing that type of triangle would be necessary. Another approach and probably easier code wise would be to create an icon for that type of shortened triangle and use PointStyle of type icon. Anyway, I want to show you what I have so far and you can see how we can extend from there and get all the line styles we want.




   class CustomLineStyle116 : LineStyle
    {
        
        protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, System.Collections.ObjectModel.Collection<SimpleCandidate> labelsInThisLayer, System.Collections.ObjectModel.Collection<SimpleCandidate> labelsInAllLayers)
        {
            LineStyle lineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.StandardColors.Black, 3, false);
            
            PointStyle pointStyle = PointStyles.CreateSimpleTriangleStyle(GeoColor.StandardColors.Black, 12);
           
           foreach (Feature feature in features)
            {
                LineShape lineShape = (LineShape)feature.GetShape();
                lineStyle.Draw(new BaseShape[] { lineShape }, canvas, labelsInThisLayer, labelsInAllLayers);

                for (int i = 0; i < lineShape.Vertices.Count - 1; i++)
                {
                    PointShape pointShape1 = new PointShape(lineShape.Vertices[i]);
                    PointShape pointShape2 = new PointShape(lineShape.Vertices[i + 1]);

                    LineShape tempLineShape = new LineShape();
                    tempLineShape.Vertices.Add(lineShape.Vertices[i]);
                    tempLineShape.Vertices.Add(lineShape.Vertices[i + 1]);

                    double angle = GetAngleFromTwoVertices(lineShape.Vertices[i], lineShape.Vertices[i + 1]);
                    pointStyle.RotationAngle = (float)angle;
                   
                    float screenDist = ExtentHelper.GetScreenDistanceBetweenTwoWorldPoints(canvas.CurrentWorldExtent, pointShape1, 
                                                                                        pointShape2, canvas.Width, canvas.Height);
                    double currentDist = Math.Round(pointShape1.GetDistanceTo(pointShape2, canvas.MapUnit, DistanceUnit.Meter), 2);
                    double worldInterval = (currentDist * 30) / screenDist;

                    double totalDist = 0;
                    while (totalDist <= currentDist)
                    {
                        PointShape tempPointShape = tempLineShape.GetPointOnALine(StartingPoint.FirstPoint, totalDist, canvas.MapUnit, DistanceUnit.Meter);
                        pointStyle.Draw(new BaseShape[] { tempPointShape }, canvas, labelsInThisLayer, labelsInAllLayers);
                        totalDist = totalDist + worldInterval;
                    }
                 }
            }
            
        }

        private double GetAngleFromTwoVertices(Vertex b, Vertex c)
        {
            double result;
            double alpha = 0;
            double tangentAlpha = (c.Y - b.Y) / (c.X - b.X);
            double Peta = Math.Atan(tangentAlpha);

            if (c.X > b.X)
            {
                alpha = 90 + (Peta * (180 / Math.PI));
            }
            else if (c.X < b.X)
            {
                alpha = 270 + (Peta * (180 / Math.PI));
            }
            else
            {
                if (c.Y > b.Y) alpha = 0;
                if (c.Y < b.Y) alpha = 180;
            }

            double offset;
            if (b.X > c.X)
            { offset = 90; }
            else { offset = -90; }

            result = alpha + offset;
            return result;
        }

    }


Lars,


 I let you know that the work on custom Linestyle according to your symbols  has progressed. We will publish a Code Community sample on that shortly. Some of those symbols are for weather fronts such as cold and warm fronts. You can see an example on the screenshot below. Thank you.



 



Hi Val, 
  
 Thanks for your effort. I’ll have a closer look at both the above code and the code you release in the community. 
  
 Thanks again. 


Lars, 
  
  You are welcome. The sample should be in the Code Community tomorrow. Thank you.

Lars,


 You can check the new Code Community sample Weather Line Style that shows how to draw cold, warm and occluded fronts which is similar to some of the examples you have. wiki.thinkgeo.com/wiki/Map_Suite_We...Line_Style


Thank you.