Select to view content in your preferred language

# IZAware in ArcGIS Pro SDK

549
4
09-07-2023 10:32 AM
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)
4 Replies
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"

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.

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

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

Occasional Contributor

Annette -

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

Ed