IZAware in ArcGIS Pro SDK

389
4
09-07-2023 10:32 AM
EdwardBlair
Occasional 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)
0 Kudos
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"

0 Kudos
EdwardBlair
Occasional 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.

0 Kudos
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();

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

 

0 Kudos
EdwardBlair
Occasional Contributor

Annette -

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

Ed