Hi,
We have a offset polyline problem I can not offset polyline as you draw (original as drawn) . How can we solve this important problem ? Or are there any alternative solution? We are using all Offset Types (Mitter ,Bevel , Round , Square) but polyline shape changes, we don not want the line to be different shape .We can offset same polyline in ArcObjects but we can not wit ArcgisPro SDK.
Here is in code and pictures in ArcgisPro SDK below :
Mitter left and right offset in the middle green polyline is original polyline
if (result.RightSide)
offsetGeometry = GeometryEngine.Instance.Offset(feature.GetShape(), distance, OffsetType.Miter, 5) as Polyline;
else
offsetGeometry = GeometryEngine.Instance.Offset(feature.GetShape(), -distance, OffsetType.Miter, 5) as Polyline;
Round left and right offset in the middle green polyline is original polyline
if (result.RightSide)
offsetGeometry = GeometryEngine.Instance.Offset(feature.GetShape(), distance, OffsetType.Round, 0) as Polyline;
else
offsetGeometry = GeometryEngine.Instance.Offset(feature.GetShape(), -distance, OffsetType.Round, 0) as Polyline;
Here is below what we want correct left and right offset code and pictures in ArcObjects :
Left and right offset in the middle green polyline is original polyline.
IConstructCurve constructCurve = new PolylineClass();
constructCurve.ConstructOffset(polycurve, Offset, ref esriConstructOffsetEnum, ref bevelRatio);
Thanks for Helping
Hello Annette, any word on the above?
While you are at it, I like to find out additional information on the following method "GeometryEngine.Instance.SideBuffer()", if you have any updates please?
Noticed that the LineCapType throws not implemented. See line number ~4820 in "ArcGIS.Core.Geometry.GeometryEngine"
Decompiled code snip from your nuget package:
public ArcGIS.Core.Geometry.Geometry SideBuffer(
Polyline polyline,
double distance,
LeftOrRightSide side,
LineCapType capType)
{
GeometryEngine.CheckForNullGeometry((ArcGIS.Core.Geometry.Geometry) polyline);
if (double.IsNaN(distance) || double.IsInfinity(distance) || distance < 0.0)
throw new ArgumentException("distance must be greater than zero");
if (capType == LineCapType.Square)
throw new ArgumentException(string.Format(GeometryResources.NotImplemented, (object) "LineCapType.Square"));
This is a bug that will be addressed in a future release. Unfortunately, I can't give you an exact date at this time. I am working on a workaround for you, but I want to test it a little bit more. It will be ready tomorrow.
Regarding SideBuffer, the corners of the buffer will always be round. The LineCapType refers only to the start and end of the line.
Can you use this workaround?
private Multipart GetOffsetUsingGraphicBuffer(Multipart multipart, double offsetDistance, LineJoinType joinType)
{
Polygon graphicBuffer = GeometryEngine.Instance.GraphicBuffer(multipart, Math.Abs(offsetDistance), joinType, LineCapType.Square, 4, 0, 96) as Polygon;
Polyline boundary = GeometryEngine.Instance.Boundary(graphicBuffer) as Polyline;
ProximityResult startResult = GeometryEngine.Instance.NearestPoint(boundary, multipart.Points[0]);
Coordinate2D coord = (Coordinate2D)(startResult.Point);
Segment firstSegment = multipart.Parts[0][0];
// Negative offset distance means the offset line will be on the left side
bool isOnRightSide = PointIsOnRightSide(firstSegment.StartCoordinate, coord, firstSegment.EndCoordinate);
if (offsetDistance > 0 && !isOnRightSide)
coord.Rotate(Math.PI, (Coordinate2D)(multipart.Points[0]));
double distanceAlongCurve1, distanceFromCurve;
LeftOrRightSide whichSide;
MapPoint point = GeometryEngine.Instance.QueryPointAndDistance(boundary, SegmentExtensionType.NoExtension, coord.ToMapPoint(), AsRatioOrLength.AsRatio, out distanceAlongCurve1, out distanceFromCurve, out whichSide);
ProximityResult endResult = GeometryEngine.Instance.NearestPoint(boundary, multipart.Points.Last());
coord = (Coordinate2D)(endResult.Point);
if (offsetDistance > 0 && !isOnRightSide)
coord.Rotate(Math.PI, (Coordinate2D)(multipart.Points.Last()));
double distanceAlongCurve2;
point = GeometryEngine.Instance.QueryPointAndDistance(boundary, SegmentExtensionType.NoExtension, coord.ToMapPoint(), AsRatioOrLength.AsRatio, out distanceAlongCurve2, out distanceFromCurve, out whichSide);
double d1 = Math.Min(distanceAlongCurve1, distanceAlongCurve2);
double d2 = Math.Max(distanceAlongCurve1, distanceAlongCurve2);
Polyline subCurve = GeometryEngine.Instance.GetSubCurve(boundary, d1, d2, AsRatioOrLength.AsRatio) as Polyline;
return subCurve;
}
private bool PointIsOnRightSide(Coordinate2D origin, Coordinate2D p1, Coordinate2D p2)
{
// The result is positive if p1 lies on right side of origin-->p2;
double part1 = (p1.X - origin.X) * (p2.Y - origin.Y),
part2 = (p1.Y - origin.Y) * (p2.X - origin.X),
result = part1 - part2;
return result > 0;
}
// Here is a test
public void GEOffsetWorkaroundTest()
{
SpatialReference spatialReference = SpatialReferences.WGS84;
var coords = new List<Coordinate2D>
{
new Coordinate2D(0.1, 0.1),
new Coordinate2D(0.2, 0.5),
new Coordinate2D(0.3, 0.1),
new Coordinate2D(0.4, 0.1),
new Coordinate2D(0.5, 0.8)
};
Polyline polyline = PolylineBuilderEx.CreatePolyline(coords, spatialReference) as Polyline;
Polyline outputOffsetPolyline = GetOffsetUsingGraphicBuffer(polyline, 0.1, LineJoinType.Miter) as Polyline;
File.WriteAllText("C:\\temp\\outputOffsetPolyline_1_.txt", outputOffsetPolyline.ToJson());
outputOffsetPolyline = GetOffsetUsingGraphicBuffer(polyline, -0.1, LineJoinType.Miter) as Polyline;
File.WriteAllText("C:\\temp\\outputOffsetPolyline_2_.txt", outputOffsetPolyline.ToJson());
outputOffsetPolyline = GetOffsetUsingGraphicBuffer(polyline, 0.1, LineJoinType.Bevel) as Polyline;
File.WriteAllText("C:\\temp\\outputOffsetPolyline_3_.txt", outputOffsetPolyline.ToJson());
outputOffsetPolyline = GetOffsetUsingGraphicBuffer(polyline, -0.1, LineJoinType.Bevel) as Polyline;
File.WriteAllText("C:\\temp\\outputOffsetPolyline_4_.txt", outputOffsetPolyline.ToJson());
outputOffsetPolyline = GetOffsetUsingGraphicBuffer(polyline, 0.1, LineJoinType.Round) as Polyline;
File.WriteAllText("C:\\temp\\outputOffsetPolyline_5_.txt", outputOffsetPolyline.ToJson());
}
Hi,
This will be fixed in the ArcGIS Pro 3.3.
Annette