DRAWING ARCS

1065
8
Jump to solution
08-03-2022 02:47 AM
FranciscoLopez
New Contributor II

Hi everyone.

I need to draw several arcs in a overlay. I need to make a function where with a location, angle and distance, draw an arc like the attached file.

0 Kudos
1 Solution

Accepted Solutions
ThadTilton
Esri Contributor

Here's the function:

private Geometry CreateDensifiedWedgeGeometry(MapPoint center, double radius, double arcAngle, double azimuth)
{
    SpatialReference spatialReference = center.SpatialReference;

    // Get the angle of the azimuth.
    var directionAngle = 90 - azimuth;
    directionAngle = (directionAngle < 0) ? directionAngle + 360 : directionAngle;
    directionAngle = (directionAngle > 360) ? directionAngle - 360 : directionAngle;

    // Subtract half of the arc angle from the direction (wedge should be split by the azimuth angle).
    var startPointDegrees = directionAngle - (arcAngle / 2);
    startPointDegrees = (startPointDegrees < 0) ? startPointDegrees + 360 : startPointDegrees;
    startPointDegrees = (startPointDegrees > 360) ? startPointDegrees - 360 : startPointDegrees;

    // Get the radian values of the angles.
    var startPointRadians = startPointDegrees * Math.PI / 180.0;
    var arcAngleRadians = arcAngle * Math.PI / 180;

    // Create an arc segment with the center point, radius, start point of the arc, arc angle, and spatial reference.
    EllipticArcSegment arc = EllipticArcSegment.CreateCircularEllipticArc(center, radius, startPointRadians, arcAngleRadians, spatialReference);

    // create the sides of the wedge (center point to start/end points of the arc).
    var startSide = new LineSegment(center, arc.StartPoint);
    //var endSide = new LineSegment(center, arc.EndPoint);

    // Create the wedge-shaped polygon.
    PolygonBuilder builder = new PolygonBuilder(spatialReference);
    // Note: only need to add one of the sides to complete the polygon.
    builder.AddPart(
        new Part(new Segment[]
        {
           startSide,
           arc
        }, spatialReference)
    );

    // Densify the arc for display in 3D.
    var densifiedPoly = GeometryEngine.Densify(builder.ToGeometry(), 100000);

    return densifiedPoly; // builder.ToGeometry();
}

 

I call it with this:

private void CreateWedgeButton_Click(object sender, RoutedEventArgs e)
{
    MapPoint origin = new MapPoint(x: 40e5, y: 5e5, SpatialReferences.WebMercator);
    Geometry wedgeGeometry = CreateDensifiedWedgeGeometry(origin, 1000000, 90, 360);
    Graphic wedgeGraphic = new Graphic(wedgeGeometry);

    var curvedGraphicsOverlay = MySceneView.GraphicsOverlays["curvedoverlay"];
    curvedGraphicsOverlay.Graphics.Add(wedgeGraphic);

    MySceneView.SetViewpoint(new Viewpoint(wedgeGeometry));
}

View solution in original post

8 Replies
ThadTilton
Esri Contributor

This seems to work, perhaps give it a test to make sure you get the correct shape based on your inputs.

private Geometry CreateWedgeGeometry(MapPoint center, double radius, double arcAngle, double azimuth)
{
    SpatialReference spatialReference = center.SpatialReference;

    // Get the angle of the azimuth.
    var directionAngle = 90 - azimuth;
    directionAngle = (directionAngle < 0) ? directionAngle + 360 : directionAngle;
    directionAngle = (directionAngle > 360) ? directionAngle - 360 : directionAngle;            

    // Subtract half of the arc angle from the direction (wedge should be split by the azimuth angle).
    var startPointDegrees = directionAngle - (arcAngle / 2);
    startPointDegrees = (startPointDegrees < 0) ? startPointDegrees + 360 : startPointDegrees;
    startPointDegrees = (startPointDegrees > 360) ? startPointDegrees - 360 : startPointDegrees;

    // Get the radian values of the angles.
    var startPointRadians = startPointDegrees * Math.PI / 180.0;
    var arcAngleRadians = arcAngle * Math.PI / 180;

    // Create an arc segment with the center point, radius, start point of the arc, arc angle, and spatial reference.
    EllipticArcSegment arc = EllipticArcSegment.CreateCircularEllipticArc(center, radius, startPointRadians, arcAngleRadians, spatialReference);

    // create the sides of the wedge (center point to start/end points of the arc).
    var startSide = new LineSegment(center, arc.StartPoint);
    //var endSide = new LineSegment(center, arc.EndPoint);
            
    // Create the wedge-shaped polygon.
    PolygonBuilder builder = new PolygonBuilder(spatialReference);
    // Note: only need to add one of the sides to complete the polygon.
    builder.AddPart(
        new Part(new Segment[]
        {
            startSide,
            arc
        }, spatialReference)
    );

    return builder.ToGeometry();
}

 Based on your image, "arcAngle" is α, and "radius" is D. The "azimuth" defines the orientation (compass direction) of the wedge. To create something like what's shown in your image, you'd call it like this:

Geometry wedge = CreateWedgeGeometry(originPoint, 1000000, 90.0, 360.0);

 Hope that helps, Thad

FranciscoLopez
New Contributor II

Hi, first of all, thanks a lot for your help. I have used your code to make this:

MapView.CreateAimingZone(_latitude, _longitude, 0.078,90,180);

public void CreateAimingZone(double latitude, double longitude, double radius, double arcAngle, double azimuth)
{
MapPoint center = new MapPoint(longitude,latitude);
Graphic AimiinZone = CreateWedgeGeometry(center, radius, arcAngle, azimuth);
_ringRange_GO.Graphics.Add(AimiinZone);
}

private Graphic CreateWedgeGeometry(MapPoint center, double radius, double arcAngle, double azimuth)
{
SpatialReference spatialReference = center.SpatialReference;

// Get the angle of the azimuth.
var directionAngle = 90 - azimuth;
directionAngle = (directionAngle < 0) ? directionAngle + 360 : directionAngle;
directionAngle = (directionAngle > 360) ? directionAngle - 360 : directionAngle;

// Subtract half of the arc angle from the direction (wedge should be split by the azimuth angle).
var startPointDegrees = directionAngle - (arcAngle / 2);
startPointDegrees = (startPointDegrees < 0) ? startPointDegrees + 360 : startPointDegrees;
startPointDegrees = (startPointDegrees > 360) ? startPointDegrees - 360 : startPointDegrees;

// Get the radian values of the angles.
var startPointRadians = startPointDegrees * Math.PI / 180.0;
var arcAngleRadians = arcAngle * Math.PI / 180;

// Create an arc segment with the center point, radius, start point of the arc, arc angle, and spatial reference.
EllipticArcSegment arc = EllipticArcSegment.CreateCircularEllipticArc(center, radius, startPointRadians, arcAngleRadians, spatialReference);

// create the sides of the wedge (center point to start/end points of the arc).
var startSide = new LineSegment(center, arc.StartPoint);
//var endSide = new LineSegment(center, arc.EndPoint);

// Create the wedge-shaped polygon.
PolygonBuilder builder = new PolygonBuilder(spatialReference);
// Note: only need to add one of the sides to complete the polygon.
builder.AddPart(
new Part(new Segment[]
{
startSide,
arc
}, spatialReference)
);

Graphic ellipseGraphic = new Graphic(builder.ToGeometry());

//return builder.ToGeometry();
return ellipseGraphic;
}

 

My result is in the attached file, I am doing something wrong. I have made a tringle.

Other different is a use de value 1000000 in radius I can't see anything, but i I use 0.08 the Radius, Distance is 8Km.

 

0 Kudos
FranciscoLopez
New Contributor II

I forget I and using SceneView not MapView. I want to draw it in SceneView . Do you know how?

0 Kudos
FranciscoLopez
New Contributor II

Hi ThadTilton

Please, see the link EllipticArcSegment.CreateCircularEllipticArc To see what is the problem with EllipticArcSegment.CreateCircularEllipticArc

Anyway, Thanks a lot for your help. I have learned a lot.

Regards

0 Kudos
ThadTilton
Esri Contributor

Hey Francisco, for display in 3D, you need to densify the arc. This will represent the arc as a series of linear segments rather than a true curve. The tricky part might be finding the ideal "maxSegmentLength" to get a smooth curve (without going too small, which could hurt performance). Here's an example of densifying so the returned "curve" is composed of segments not less than 10,000 meters (10 km).

// Densify the arc for display in 3D.
var densifiedPoly = GeometryEngine.Densify(builder.ToGeometry(), 10000);
return densifiedPoly; // builder.ToGeometry();

 

0 Kudos
FranciscoLopez
New Contributor II

I am sorry  ThadTilton, I can't get your result. Please could you send me the code to get the result you attached?

0 Kudos
ThadTilton
Esri Contributor

Here's the function:

private Geometry CreateDensifiedWedgeGeometry(MapPoint center, double radius, double arcAngle, double azimuth)
{
    SpatialReference spatialReference = center.SpatialReference;

    // Get the angle of the azimuth.
    var directionAngle = 90 - azimuth;
    directionAngle = (directionAngle < 0) ? directionAngle + 360 : directionAngle;
    directionAngle = (directionAngle > 360) ? directionAngle - 360 : directionAngle;

    // Subtract half of the arc angle from the direction (wedge should be split by the azimuth angle).
    var startPointDegrees = directionAngle - (arcAngle / 2);
    startPointDegrees = (startPointDegrees < 0) ? startPointDegrees + 360 : startPointDegrees;
    startPointDegrees = (startPointDegrees > 360) ? startPointDegrees - 360 : startPointDegrees;

    // Get the radian values of the angles.
    var startPointRadians = startPointDegrees * Math.PI / 180.0;
    var arcAngleRadians = arcAngle * Math.PI / 180;

    // Create an arc segment with the center point, radius, start point of the arc, arc angle, and spatial reference.
    EllipticArcSegment arc = EllipticArcSegment.CreateCircularEllipticArc(center, radius, startPointRadians, arcAngleRadians, spatialReference);

    // create the sides of the wedge (center point to start/end points of the arc).
    var startSide = new LineSegment(center, arc.StartPoint);
    //var endSide = new LineSegment(center, arc.EndPoint);

    // Create the wedge-shaped polygon.
    PolygonBuilder builder = new PolygonBuilder(spatialReference);
    // Note: only need to add one of the sides to complete the polygon.
    builder.AddPart(
        new Part(new Segment[]
        {
           startSide,
           arc
        }, spatialReference)
    );

    // Densify the arc for display in 3D.
    var densifiedPoly = GeometryEngine.Densify(builder.ToGeometry(), 100000);

    return densifiedPoly; // builder.ToGeometry();
}

 

I call it with this:

private void CreateWedgeButton_Click(object sender, RoutedEventArgs e)
{
    MapPoint origin = new MapPoint(x: 40e5, y: 5e5, SpatialReferences.WebMercator);
    Geometry wedgeGeometry = CreateDensifiedWedgeGeometry(origin, 1000000, 90, 360);
    Graphic wedgeGraphic = new Graphic(wedgeGeometry);

    var curvedGraphicsOverlay = MySceneView.GraphicsOverlays["curvedoverlay"];
    curvedGraphicsOverlay.Graphics.Add(wedgeGraphic);

    MySceneView.SetViewpoint(new Viewpoint(wedgeGeometry));
}
FranciscoLopez
New Contributor II

Thanks a lot. My problem is than I am new in GIS and I have problem to understand the concepts. I have to learn about the different Dantum. Any way, thanks a lot for your solution.

0 Kudos