Announcement

Collapse
No announcement yet.

[Solved] Drawing a circle ?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • [Solved] Drawing a circle ?

    Hello all, I'm having trouble getting my circles to draw correctly. Hopefully someone can tell me what I am doing wrong and point me in the right direction. Here is my code and some screen shots. In the shots you can see how the circle is rendered at an angle....I need it to render as flat as possible to the terrain. Thanks to anyone that might be able to help.

    Code:
    public override void Render(DrawArgs drawArgs)
            {
                if (!isInitialized)
                {
                    return;
                }
    
                if (timedout)
                    return;
    
    
                drawArgs.device.VertexFormat = CustomVertex.PositionColored.Format;
                Cull currentCull = drawArgs.device.RenderState.CullMode;
                drawArgs.device.TextureState[0].ColorOperation = TextureOperation.Disable;
                drawArgs.device.RenderState.CullMode = Cull.None;
    
                Vector3 referenceCenter = new Vector3(
                    (float)drawArgs.WorldCamera.ReferenceCenter.X,
                    (float)drawArgs.WorldCamera.ReferenceCenter.Y,
                    (float)drawArgs.WorldCamera.ReferenceCenter.Z);
    
                drawArgs.device.Transform.World = Matrix.Translation(
                    (float)-drawArgs.WorldCamera.ReferenceCenter.X,
                    (float)-drawArgs.WorldCamera.ReferenceCenter.Y,
                    (float)-drawArgs.WorldCamera.ReferenceCenter.Z
                    );
    
    
             
                double terrainAlt = parentWorld.TerrainAccessor.GetElevationAt(circleInfo.X, circleInfo.Y,
                    (100.0 / drawArgs.WorldCamera.ViewRange.Degrees));
    
                if (circleInfo.Z < terrainAlt)
                    circleInfo.Z = (float)terrainAlt;
    
                Vector3 startPoint = MathEngine.SphericalToCartesian(circleInfo.X, circleInfo.Y,
                    parentWorld.EquatorialRadius + circleInfo.Z * World.Settings.VerticalExaggeration);
    
    
                double circleRadius = 40;//circleInfo.radius;
               
    
                float angle;
    
                for (int i = 0; i < circleVert.Length; i++)
                {
                    angle = (float)(i * 2 * Math.PI / (circleVert.Length - 1));
                    circleVert[i].X = (float)(startPoint.X + Math.Sin(angle) * circleRadius);
                    circleVert[i].Y = (float)(startPoint.Y + Math.Cos(angle) * circleRadius);
                    circleVert[i].Z = startPoint.Z;
    
                    circleVert[i].Color = Color.Red.ToArgb();
                }
    
    
                try
                {
                    drawArgs.device.TextureState[0].ColorOperation = TextureOperation.Disable;
                    
                    drawArgs.device.DrawUserPrimitives(PrimitiveType.LineStrip, circleVert.Length - 1, circleVert);
                    drawArgs.device.Transform.World = drawArgs.WorldCamera.WorldMatrix;
                    drawArgs.device.Transform.World = drawArgs.WorldCamera.WorldMatrix;
                    drawArgs.device.VertexFormat = CustomVertex.PositionColored.Format;
                }
            
    
                catch (Exception ex)
                {
    
                }
      
                
            }
    1st Screen Shot: The circle should be rotated to be parallel with the ground



    2nd Screen Shot: This if from directly above...looks more oval than a circular
    Attached Files
    Last edited by patmurris; 12-30-2008, 02:05 AM. Reason: Solved

  • #2
    There are at least two things you have to consider:

    1. Drawing a circle in lat-lon space will only yield a 'round' circle at the equator since longitude lines get closer to each other as you move away from the equator. To properly compute the lat-lon coordinates of your circle circumference points, you have to use spherical triangle equations or great circle formulas.

    2. To get your circle parallel to the ground, before drawing it, you have to operate two rotations to account for it particular latitude and longitude.

    See this other thread:
    http://forum.worldwindcentral.com/sh...ghlight=circle

    Edit: my answer was a bit quick and looking again at your code, i see you draw your circle in cartesian space rather then lat-lon space as i thought, but you do so in the x-y plane hoping it will be parallel to the ground. What i believe you do get is a round circle but with the wrong orientation.

    There are two ways you can achieve a round circle with the proper orientation:

    1. Compute its perimeter points latitude and longitude using spherical triangle equation (great circle), then convert those coordinates to cartesian.

    2. Draw a one unit radius square at the origin in the x-y plane, then operate four transforms before drawing it. The transforms will be a translation to the globe surface, a scaling to get the proper circle size, and two rotations to account for latitude and longitude. You may have a look at the SkyGradient plugin code to get a hint of how to procede that way.
    Last edited by patmurris; 12-26-2008, 07:22 PM.
    My World Wind Java Blog & WW.net Plugins page

    Comment


    • #3
      Thanks for the reply...I took a look at that code and tried to apply it without much luck. I did find an example of the matrix scaling and rotation in the Waving Flags plugin that seems to be exactly what I need...my attempt at incorporating that code failed too. My understanding of 3d matrix rotation is minimal to say the least. Aslo I wasnt sure how to do the scaling so I just run different numbers that I see used in some of the other plugins (1, 10, 1000, vertical exageration)..none of which are working for me.

      Ill post the code changes and some screen shots below and hopefully y'all can see what Im doing wrong. Thanks again for your help.

      Code:
              public override void Render(DrawArgs drawArgs)
              {
      
                  if (!isInitialized)
                  {
                      return;
                  }
      
                  if (timedout)
                      return;
      
      
                  drawArgs.device.Transform.World = Matrix.RotationY((float)MathEngine.DegreesToRadians(90));
      
                  drawArgs.device.Transform.World *= Matrix.Scaling(1.0f, 1.0f, 1.0f);
      
                  drawArgs.device.Transform.World *= Matrix.RotationY((float)-MathEngine.DegreesToRadians(circleInfo.X));
      
                  drawArgs.device.Transform.World *= Matrix.RotationZ((float)MathEngine.DegreesToRadians(circleInfo.Y));
                          
      
                  Vector3 rc = new Vector3(
      
                      (float)drawArgs.WorldCamera.ReferenceCenter.X,
      
                      (float)drawArgs.WorldCamera.ReferenceCenter.Y,
      
                      (float)drawArgs.WorldCamera.ReferenceCenter.Z
      
                      );
      
                  double terrainAlt = parentWorld.TerrainAccessor.GetElevationAt(circleInfo.X, circleInfo.Y,
                      (100.0 / drawArgs.WorldCamera.ViewRange.Degrees));
      
                  if (circleInfo.Z < terrainAlt)
                      circleInfo.Z = (float)terrainAlt;
      
                  Vector3 startPoint = MathEngine.SphericalToCartesian(circleInfo.X, circleInfo.Y,
                      parentWorld.EquatorialRadius + circleInfo.Z * World.Settings.VerticalExaggeration);
      
                  drawArgs.device.Transform.World *= Matrix.Translation(startPoint - rc);
      
              
                  double circleRadius = 400000;//circleInfo.radius;
      
                  float angle;
      
                  for (int i = 0; i < circleVert.Length; i++)
                  {
                      
                      angle = (float)(i * 2 * Math.PI / (circleVert.Length - 1));
                      circleVert[i].X = (float)(startPoint.X + Math.Sin(angle) * circleRadius);
                      circleVert[i].Y = (float)(startPoint.Y + Math.Cos(angle) * circleRadius);
                      circleVert[i].Z = startPoint.Z;
                      circleVert[i].Color = Color.Red.ToArgb();
                      
      
                  }
      
      
                  drawArgs.device.VertexFormat = CustomVertex.PositionColored.Format;
                  Cull currentCull = drawArgs.device.RenderState.CullMode;
                  drawArgs.device.TextureState[0].ColorOperation = TextureOperation.Disable;
                  drawArgs.device.RenderState.CullMode = Cull.None;
      
                  
                  try
                  {
                      
                      drawArgs.device.TextureState[0].ColorOperation = TextureOperation.Disable;
                      drawArgs.device.DrawUserPrimitives(PrimitiveType.LineStrip, circleVert.Length - 1, circleVert);
                      drawArgs.device.Transform.World = drawArgs.WorldCamera.WorldMatrix;
                      drawArgs.device.VertexFormat = CustomVertex.PositionColored.Format;
                  
                  }
              catch (Exception ex)
                  {
      
                  }
        
                  
              }



      Comment


      • #4
        I figured it out...I forgot to take the start point out of the circle calculations. Its working great now...Thanks again for the help.

        Comment


        • #5
          PolygonFeature Can use to draw Circle ?

          How?

          I want coding in plug in file.

          thank you

          Comment


          • #6
            I know this thread is old, but I thought this code that works in World Wind Java code might help someone else. It returns a circle of Positions around a given lat lon at a specified radius.
            /**
            * This method generates an arrayList of lat lon Positions that make a circle around a defined latitude and longitude.
            * The circle's radius in meters is passed in so it can know how big to make the circle.
            *
            * To use the Positions this method returns you could do something similar to:
            * Path ringPath = new Path(ringPositions);
            * From there you would just set your attributes and add the path to a RenderableLayer.
            *
            * @param ringCenterLat - The latitude in the the center of ring we will generate.
            * @param ringCenterLon - The longitude in the the center of ring we will generate.
            * @param radius - The radius (in Meters) of the ring you want to generate.
            * @param numPoints - The number of Lat Lon Positions you want generated around the ring. 360 is recommended.
            */
            private ArrayList<Position> buildSingleRing(Double ringCenterLat, Double ringCenterLon, Double radius, Double numPoints)
            {
            ArrayList<Position> ringPositions = new ArrayList<Position>(); //Create an array list that will hold our positions the define our ring. (i.e. holds the ring defining lat lon Positions)

            double dist_rad = radius / 6378137.0; //Gets the ring's radius distance in Radians. (To do this we divide the radius of the ring by the radius of the globe.)
            double numDegrees = 360 / numPoints; //This generates how many degrees we will have between each point we will generate around our ring.

            Angle curr = Angle.fromRadians(0); //This holds our current angle and is increased by our numDegrees for each new Position generated around the ring.
            Angle latAngle = Angle.fromRadians(0); //This Angle holds the latitude of the point we generate. (Note: An Angle can be set in Radians or degrees, and either can be retrieved from it. We set ours in Radians and retrieve it in degrees for our Positions.)
            Angle lonAngle = Angle.fromRadians(0); //This Angle holds the longitude of the point we generate. (Note: An angle can be set in Radians or degrees, and either can be retrieved from it. We set ours in Radians and retrieve it in degrees for our Positions.)
            Double tempLonAngle = 0.0D; //Holds some of the math used in generating the Longitude to make the formula easier to read.

            int alt = 0;

            for (int i = 0; i <= numPoints; i++) //Loop through each of the points around the ring (so we can generate our lat lons)
            {
            curr = Angle.fromDegrees((double) i * numDegrees); //calculate our current angle. I.e. multiply our iterator by our numDegrees and store it as an angle.

            latAngle = Angle.fromRadians(Math.asin(Math.sin(Mat h.toRadians(ringCenterLat)) * Math.cos(dist_rad) + Math.cos(Math.toRadians(ringCenterLat)) * Math.sin(dist_rad) * Math.cos(curr.radians))); //Finds our latAngle using a fancy formula (using Radians)
            tempLonAngle = Math.atan2(Math.sin(curr.radians) * Math.sin(dist_rad) * Math.cos(Math.toRadians(ringCenterLat)), Math.cos(dist_rad) - Math.sin(Math.toRadians(ringCenterLat)) * Math.sin(latAngle.radians)); //Does part of the math needed to get our Lon (using Radians)
            lonAngle = Angle.fromRadians(((Math.toRadians(ringC enterLon) + tempLonAngle + Math.PI) % (2 * Math.PI)) - Math.PI); //Finds our lonAngle using a fancy formula (using Radians) (Also utilizes our previous temp calculation)

            alt = 10000; //Use any alt of your choice, In my app I used the ground alt at the location of the lat lon by using controller.getWWd().getModel().getGlobe( ).getElevation(latAngle.degrees, lonAngle.degrees); But the alt won't matter anyway if using a path that is clamped to ground and terrain conforming.)

            ringPositions.add(new Position(latAngle, lonAngle, alt)); //Adds each new position it generates to our List of pathPositions.

            }//End of for loop

            return ringPositions;
            }//End of buildSingleRing method

            Comment

            Working...
            X