IZAware in ArcGIS Pro SDK

1621
4
09-07-2023 10:32 AM
EdwardBlair
Frequent Contributor

In ArcObjects there is the IZAware interface we can use to make an existing 2D geometry aware of Z-values.   I can't find the equivalent in the ArcGIS Pro SDK -- but there must be a way to do this.  How can I, for example, change a polyline that may include a parametric curve from a 2D polyline to a 3D polyline?

Tags (3)
This widget could not be displayed.
This widget could not be displayed.
4 Replies
CharlesMacleod
Esri Regular Contributor

geometries are immutable. to convert 2d to 3d u will need a builder. In your specific example,  you will need a PolygonBuilderEx . Note that is has a HasZ property which is get and set. There is also a constructor overload that takes a polyline as its input.

 

Lots of examples here in the Geometry snippets. Ctrl-F "PolylineBuilderEx"

This widget could not be displayed.
This widget could not be displayed.
EdwardBlair
Frequent Contributor

Right.   I've looked at the examples in the Geometry snippets, but none seems to completely satisfy the need to ensure all components are z-aware.   I could get all the points from the source polyline, update them to 3-D and re-create the polyline as 3-D, but that would lose any parametric curves.

This widget could not be displayed.
This widget could not be displayed.
AnnetteLocke
Esri Contributor

If you set HasZ = true in the builder, then all start and end points will have the HasZ property set to true too. Here is some code to set the z-values in the points while still preserving the curve segments. 

/////////////////////////////////

LineSegment line = LineBuilderEx.CreateLineSegment(new Coordinate2D(0, 0), new Coordinate2D(3, 3));

MapPoint start = MapPointBuilderEx.CreateMapPoint(3, 3);
MapPoint end = MapPointBuilderEx.CreateMapPoint(7, 3);
Coordinate2D center = new Coordinate2D(5, 5);
EllipticArcSegment arc = EllipticArcBuilderEx.CreateCircularArc(start, end, center, ArcOrientation.ArcCounterClockwise);

Polyline polyline = PolylineBuilderEx.CreatePolyline(new Segment[] { line, arc });
Assert.IsFalse(polyline.HasZ);

PolylineBuilderEx polylineBuilder = new PolylineBuilderEx(polyline);
polylineBuilder.HasZ = true;
Polyline polyline3D = polylineBuilder.ToGeometry();

var points = polyline3D.Points;
foreach (MapPoint p in points)
  Assert.IsTrue(p.HasZ);

var part = polyline3D.Parts[0];
int numSegments = part.Count;

for (int i = 0; i < numSegments; i++)
{
  Segment segment = part[i];

  MapPointBuilderEx pointBuilder = new MapPointBuilderEx(segment.StartPoint);
  pointBuilder.Z = i + 1;
  MapPoint startPoint = pointBuilder.ToGeometry();

  pointBuilder = new MapPointBuilderEx(segment.EndPoint);
  pointBuilder.Z = i + 2;
  MapPoint endPoint = pointBuilder.ToGeometry();

  SegmentType segmentType = segment.SegmentType;
  SegmentBuilderEx segmentBuilder = null;
  switch (segmentType)
  {
    case SegmentType.Line:
      segmentBuilder = new LineBuilderEx((LineSegment)segment);
      break;
    case SegmentType.Bezier:
      segmentBuilder = new CubicBezierBuilderEx((CubicBezierSegment)segment);
      break;
    case SegmentType.EllipticArc:
      segmentBuilder = new EllipticArcBuilderEx((EllipticArcSegment)segment);
      break;
  }

  segmentBuilder.StartPoint = startPoint;
  segmentBuilder.EndPoint = endPoint;
  segment = segmentBuilder.ToSegment();

  polylineBuilder.ReplaceSegment(0, i, segment);
}

polyline3D = polylineBuilder.ToGeometry();

/////////////////////////////////

 

This widget could not be displayed.
This widget could not be displayed.
EdwardBlair
Frequent Contributor

Annette -

Pretty interesting.   I will give this a try.  Thanks much!

Ed

This widget could not be displayed.
This widget could not be displayed.