/// <summary> /// 绘制椭圆 /// </summary> /// <params name="pEnvelope"></params> public void DrawEllipse(IEnvelope pEnvelope) { IFeatureLayer pFeatureLayer = m_pCurrentLayer as IFeatureLayer; IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass; IConstructEllipticArc constructEllipticArc = new EllipticArcClass(); constructEllipticArc.ConstructEnvelope(pEnvelope); IEllipticArc ellipse = constructEllipticArc as IEllipticArc; ISegment segment = ellipse as ISegment; ISegmentCollection pPolyline = new Polyline() as ISegmentCollection; object Missing = Type.Missing; pPolyline.AddSegment(segment, ref Missing, ref Missing); IGeometry poly = pPolyline as IGeometry; IFeature pCircleFeature = pFeatureClass.CreateFeature(); pCircleFeature.Shape = poly as PolylineClass; pCircleFeature.Store(); //局部刷新 IInvalidArea pInvalidArea = new InvalidAreaClass(); pInvalidArea.Add(poly); pInvalidArea.Display = m_hookHelper.ActiveView.ScreenDisplay; pInvalidArea.Invalidate((short)esriScreenCache.esriAllScreenCaches); }
/// <summary> /// 转换包络为椭圆线 /// </summary> /// <param name="geometry">ESRI几何形状接口</param> /// <returns>ESRI几何形状接口的椭圆线</returns> public static IGeometry ConvertEnvelopeToEllipticArc(IGeometry geometry) { if ((IsValidGeometry(geometry)) && (geometry is IEnvelope)) { IEnvelope envelope = (IEnvelope)geometry; IPoint point = CreatePointByCoord((envelope.XMin + envelope.XMax) / 2, envelope.YMin); IEllipticArc ellipticArc = new EllipticArcClass(); (ellipticArc as IConstructEllipticArc).ConstructTwoPointsEnvelope(point, point, envelope, esriArcOrientation.esriArcClockwise); return(ellipticArc); } else { return(null); } }
public override void OnMouseMove(int Button, int Shift, int X, int Y) { m_pMovePoint = m_hookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y); m_pMovePoint = GIS.GraphicEdit.SnapSetting.getSnapPoint(m_pMovePoint); if (m_lMouseDownCount == 1) { m_bCreated = false; IEnvelope pEnv = new EnvelopeClass(); pEnv.UpperLeft = m_pFirstPoint; pEnv.LowerRight = m_pMovePoint; IConstructEllipticArc pEllipArc = new EllipticArcClass(); pEllipArc.ConstructEnvelope(pEnv); m_pEllipticArc = pEllipArc as IEllipticArc; m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewForeground, null, null); } DataEditCommon.g_pAxMapControl.Focus(); }
public void CanTestEllipticArc() { IFeatureClass fc = CreateLineClass(_testWs, "CanTestEllipticArc"); IFeature row1 = fc.CreateFeature(); IConstructEllipticArc arc = new EllipticArcClass(); arc.ConstructEnvelope(GeometryFactory.CreateEnvelope(0, 0, 100, 10)); row1.Shape = CreatePolyLine((ISegment)arc); row1.Store(); var test = new QaMinSegAngle(fc, 0.1, true); var runner = new QaContainerTestRunner(1000, test); runner.Execute(); Assert.AreEqual(0, runner.Errors.Count); }
private void DrawEllipse() { IEnvelope envelope = this.m_mapControl.TrackRectangle(); if (!envelope.IsEmpty) { IConstructEllipticArc constructEllipticArc = new EllipticArcClass(); constructEllipticArc.ConstructEnvelope(envelope); ISegment inSegment = constructEllipticArc as ISegment; ISegmentCollection segmentCollection = new RingClass(); object missing = Type.Missing; segmentCollection.AddSegment(inSegment, ref missing, ref missing); IRing ring = segmentCollection as IRing; ring.Close(); IGeometryCollection geometryCollection = new PolygonClass(); geometryCollection.AddGeometry(ring, ref missing, ref missing); this.AppendNodeToTreeList(new EllipseElementClass { Geometry = (geometryCollection as IGeometry) }); } }
private void AddEllipseElement() { IEnvelope pEnvelope = axMapControl1.TrackRectangle(); if (pEnvelope == null) { return; } IConstructEllipticArc pConstructEllipticArc = new EllipticArcClass(); //建立橢圓的Geometry pConstructEllipticArc.ConstructEnvelope(pEnvelope); IEllipticArc pEllipticArc = (IEllipticArc)pConstructEllipticArc; ISegmentCollection pSegmentCollection = new PolygonClass(); object Missing = Type.Missing; pSegmentCollection.AddSegment((ISegment)pEllipticArc, ref Missing, ref Missing); IGeometry pGeometry = pSegmentCollection as IGeometry; IEllipseElement pEllipseElement = new EllipseElementClass(); IElement pElement = pEllipseElement as IElement; pElement.Geometry = pGeometry; AddElement(pElement); }
private ISegmentCollection createSegments(Cell cell, BoostVoronoi bv, ArcConstructionMethods method, ISpatialReference spatialReference) { List <Cell> cells = bv.Cells; List <Edge> edges = bv.Edges; List <Vertex> vertices = bv.Vertices; IPoint previousEndPoint = null; ISegmentCollection segmentCollection = new PolygonClass() { SpatialReference = spatialReference }; // As per boost documentation, edges are returned in counter clockwise (CCW) rotation. // voronoi_edge_type* next() Returns the pointer to the CCW next edge within the corresponding Voronoi cell. Edges not necessarily share a common vertex (e.g. infinite edges). for (int i = cell.EdgesIndex.Count - 1; i >= 0; i--) { Edge edge = edges[cell.EdgesIndex[i]]; //If the vertex index equals -1, it means the edge is infinite. It is impossible to print the coordinates. if (!edge.IsFinite && edge.End < 0) { // this is the ending portion of a pair of infinite edges, file the previous edge with Start >= 0 Edge previous = null; for (int k = i + 1; k < cell.EdgesIndex.Count; k++) { previous = edges[cell.EdgesIndex[k]]; if (previous.End >= 0) { break; } previous = null; } if (previous == null) { for (int k = 0; k < i; k++) { previous = edges[cell.EdgesIndex[k]]; if (previous.End >= 0) { break; } previous = null; } } if (previous == null) { throw new Exception("No outbound infinite edge could be found"); } //Add a straight line segment Vertex start = vertices[previous.End]; IPoint FromPoint = new PointClass() { X = start.X, Y = start.Y, SpatialReference = spatialReference }; Vertex end = vertices[edge.Start]; IPoint ToPoint = new PointClass() { X = end.X, Y = end.Y, SpatialReference = spatialReference }; segmentCollection.AddSegment(new LineClass() { FromPoint = FromPoint, ToPoint = ToPoint, SpatialReference = spatialReference }); previousEndPoint = ToPoint; } else if (edge.IsFinite) { Vertex start = vertices[edge.End]; IPoint FromPoint = new PointClass() { X = start.X, Y = start.Y, SpatialReference = spatialReference }; if (previousEndPoint != null) { if ((Math.Abs(previousEndPoint.X - FromPoint.X) > 0.05 || Math.Abs(previousEndPoint.X - FromPoint.X) > 0.05)) { throw new Exception("Significant change between last end point and current start point"); } else { FromPoint = previousEndPoint; } } Vertex end = vertices[edge.Start]; IPoint ToPoint = new PointClass() { X = end.X, Y = end.Y, SpatialReference = spatialReference }; if (method == ArcConstructionMethods.Straight || edge.IsLinear) { segmentCollection.AddSegment(new LineClass() { FromPoint = FromPoint, ToPoint = ToPoint, SpatialReference = spatialReference }); previousEndPoint = ToPoint; } else { // We need three points, use start, end, mid-point between focus and directrix Cell twinCell = cells[edges[edge.Twin].Cell]; VPoint pointSite; VSegment lineSite; if (cell.ContainsPoint && twinCell.ContainsSegment) { pointSite = bv.RetrieveInputPoint(cell); lineSite = bv.RetrieveInputSegment(twinCell); } else if (cell.ContainsSegment && twinCell.ContainsPoint) { pointSite = bv.RetrieveInputPoint(twinCell); lineSite = bv.RetrieveInputSegment(cell); } else { throw new Exception("Invalid edge, curves should only be present between a point and a line"); } double scaleFactor = Convert.ToDouble(bv.ScaleFactor); IPoint aoPointSite = new Point() { X = Convert.ToDouble(pointSite.X) / scaleFactor, Y = Convert.ToDouble(pointSite.Y) / scaleFactor, SpatialReference = spatialReference }; ISegment aoLineSite = new LineClass() { FromPoint = new PointClass() { X = Convert.ToDouble(lineSite.Start.X) / scaleFactor, Y = Convert.ToDouble(lineSite.Start.Y) / scaleFactor, SpatialReference = spatialReference }, ToPoint = new PointClass() { X = Convert.ToDouble(lineSite.End.X) / scaleFactor, Y = Convert.ToDouble(lineSite.End.Y) / scaleFactor, SpatialReference = spatialReference }, SpatialReference = spatialReference }; if (method == ArcConstructionMethods.Approximate) { List <Vertex> sampledVerticed = null; try { sampledVerticed = bv.SampleCurvedEdge(edge, aoLineSite.Length / 10); } catch (FocusOnDirectixException e) { //Log any exception here is required sampledVerticed = new List <Vertex>() { start, end }; } catch (UnsolvableVertexException e) { sampledVerticed = new List <Vertex>() { start, end }; } sampledVerticed.Reverse(); List <IPoint> discretizedEdge = sampledVerticed.Select( p => new Point() { X = p.X, Y = p.Y } ).ToList <IPoint>(); IPoint prev = discretizedEdge[0]; foreach (IPoint v in discretizedEdge.Skip(1)) { segmentCollection.AddSegment(new LineClass() { FromPoint = new Point() { X = prev.X, Y = prev.Y, SpatialReference = spatialReference }, ToPoint = new Point() { X = v.X, Y = v.Y, SpatialReference = spatialReference }, SpatialReference = spatialReference }); prev = v; } previousEndPoint = discretizedEdge.Last(); } else if (method == ArcConstructionMethods.Circular) { IPoint nearPoint = ((IProximityOperator)aoLineSite).ReturnNearestPoint(aoPointSite, esriSegmentExtension.esriNoExtension); IPoint midpoint = new PointClass() { X = (nearPoint.X + aoPointSite.X) / 2, Y = (nearPoint.Y + aoPointSite.Y) / 2, SpatialReference = spatialReference }; IConstructCircularArc constArc = new CircularArcClass() { SpatialReference = spatialReference }; constArc.ConstructThreePoints(FromPoint, midpoint, ToPoint, false); ICircularArc arc = (ICircularArc)constArc; if (!arc.IsMinor) { constArc = new CircularArcClass() { SpatialReference = spatialReference }; constArc.ConstructEndPointsRadius(FromPoint, ToPoint, !arc.IsCounterClockwise, arc.Radius, true); arc = (ICircularArc)constArc; } segmentCollection.AddSegment((ISegment)arc); previousEndPoint = arc.ToPoint; } else if (method == ArcConstructionMethods.Ellipse) { IPoint nearPoint = ((IProximityOperator)aoLineSite).ReturnNearestPoint(aoPointSite, esriSegmentExtension.esriExtendTangents); nearPoint.SpatialReference = spatialReference; ILine lineToFocus = new LineClass() { FromPoint = nearPoint, ToPoint = aoPointSite, SpatialReference = spatialReference }; ILine semiMajor = new LineClass() { SpatialReference = spatialReference }; lineToFocus.QueryTangent(esriSegmentExtension.esriExtendTangentAtTo, 1, true, 100 * lineToFocus.Length, semiMajor); IPoint center = new PointClass() { X = (semiMajor.FromPoint.X + semiMajor.ToPoint.X) / 2, Y = (semiMajor.FromPoint.Y + semiMajor.ToPoint.Y) / 2, SpatialReference = spatialReference }; double minor_length = Math.Sqrt( Math.Pow(distance(semiMajor.FromPoint, ToPoint) + distance(semiMajor.ToPoint, ToPoint), 2) - Math.Pow(semiMajor.Length, 2)); IEllipticArc arc = new EllipticArcClass() { SpatialReference = spatialReference }; double rotation = lineToFocus.Angle; double from = GetAngle(center, FromPoint); arc.PutCoords(false, center, FromPoint, ToPoint, rotation, minor_length / semiMajor.Length, esriArcOrientation.esriArcMinor); segmentCollection.AddSegment((ISegment)arc); previousEndPoint = arc.ToPoint; } } } } return(segmentCollection); }
/// <summary> /// ������Բ /// </summary> /// <params name="pEnvelope"></params> public void DrawEllipse(IEnvelope pEnvelope) { IFeatureLayer pFeatureLayer = m_pCurrentLayer as IFeatureLayer; IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass; IConstructEllipticArc constructEllipticArc = new EllipticArcClass(); constructEllipticArc.ConstructEnvelope(pEnvelope); IEllipticArc ellipse = constructEllipticArc as IEllipticArc; ISegment segment = ellipse as ISegment; ISegmentCollection pPolyline = new Polyline() as ISegmentCollection; object Missing = Type.Missing; pPolyline.AddSegment(segment, ref Missing, ref Missing); IGeometry poly = pPolyline as IGeometry; IFeature pCircleFeature = pFeatureClass.CreateFeature(); pCircleFeature.Shape = poly as PolylineClass; pCircleFeature.Store(); //�ֲ�ˢ�� IInvalidArea pInvalidArea = new InvalidAreaClass(); pInvalidArea.Add(poly); pInvalidArea.Display = m_hookHelper.ActiveView.ScreenDisplay; pInvalidArea.Invalidate((short)esriScreenCache.esriAllScreenCaches); }
/// <summary> /// 生成椭圆 /// </summary> public IEllipticArc GenerateEllipticArc(IPoint pCenterPoint, double rotationAngle, double Descripe, double Seismic) { Core.DAL.DisaParameter disapara = new DAL.DisaParameter(); List <Core.Model.DisaParameter> listdisapara = new List <Model.DisaParameter>(); listdisapara = disapara.GetList();//读取灾区范围参数 double MajorAxis = 0; double MinorAxis = 0; for (int i = 0; i < listdisapara.Count; i++) { if (listdisapara[i].isMajorAxis) { //根据地震等级和烈度计算出长短轴 MajorAxis = System.Math.Pow(10, (listdisapara[i].A + listdisapara[i].B * Convert.ToDouble(Descripe) - Seismic) / listdisapara[i].C) - listdisapara[i].D;//长半轴 } else { MinorAxis = System.Math.Pow(10, (listdisapara[i].A + listdisapara[i].B * Convert.ToDouble(Descripe) - Seismic) / listdisapara[i].C) - listdisapara[i].D;//短半轴 } } if (MajorAxis <= 0 || MinorAxis <= 0) { MessageBox.Show("输入烈度过大!"); return(null); } double ratio; if (MajorAxis > MinorAxis) { ratio = MinorAxis / MajorAxis; } else { ratio = MajorAxis / MinorAxis; } IEllipticArc ellipticArc = new EllipticArcClass(); //ellipticArc.PutCoordsByAngle(基准,中心点,起点角度,椭圆圆心角,旋转角度,长轴,长短轴之比);轴长单位为米,角度单位为弧度 ellipticArc.PutCoordsByAngle(false, pCenterPoint, 0, 2 * Math.PI, rotationAngle * Math.PI / 180, (double)MajorAxis / Core.Generic.SysEnviriment.LengthPerRad * 2, ratio); ISegment segment = ellipticArc as ISegment; ISegmentCollection polygon = new Polygon() as ISegmentCollection; object Missing = Type.Missing; polygon.AddSegment(segment, ref Missing, ref Missing); //图上显示 Color color = Color.Red; ISymbol symbol = CreateSimpleFillSymbol(color, 1, esriSimpleFillStyle.esriSFSHollow); AddElement(polygon as IGeometry, symbol, "result"); IEnvelope envelope; envelope = ellipticArc.Envelope; if (!envelope.IsEmpty) { envelope.Expand(1, 1, true); } mapControl.Extent = envelope; this.mapControl.Refresh(); return(ellipticArc); }
//确定键 private void buttonOK_Click(object sender, EventArgs e) { double dL = 0.0, dB = 0.0, dZJ = 0.0, dTransAngle = 0.0; bool bL = double.TryParse(textBoxLong.Text, out dL); //经度 bool bB = double.TryParse(textBoxLat.Text, out dB); //纬度 bool bZJ = double.TryParse(textBoxLevel.Text, out dZJ); //震级 bool bTransAngle = double.TryParse(txtTransAngle.Text, out dTransAngle); //旋转角 time = textBoxTime.Text; //开启编辑状态 IWorkspaceFactory pWorkspaceFactory = new AccessWorkspaceFactoryClass(); IFeatureWorkspace pFeatureWorkspace = pWorkspaceFactory.OpenFromFile(dataFile, 0) as IFeatureWorkspace; IWorkspaceEdit pWorkspaceEdit = pFeatureWorkspace as IWorkspaceEdit; pWorkspaceEdit.StartEditing(false); pWorkspaceEdit.StartEditOperation(); //插入震中点数据 IFeatureClass pFeatureClassPoint = pFeatureLayerPoint.FeatureClass; IFeatureClassWrite fwritePoint = pFeatureClassPoint as IFeatureClassWrite; IFeature pFeaturePoint = pFeatureClassPoint.CreateFeature(); IPointCollection pointCollection = new MultipointClass(); IPoint pPoint = new PointClass(); IGeoDataset pGeoDataset = pFeatureClassPoint as IGeoDataset; //记录空间投影信息 ISpatialReference spatialReference = pGeoDataset.SpatialReference; //输入经纬度 pPoint.PutCoords(dL, dB); pPoint.SpatialReference = spatialReference; pointCollection.AddPoint(pPoint, ref _missing, ref _missing); pFeaturePoint.Shape = pointCollection as IGeometry; //设置“标注”属性值 pFeaturePoint.set_Value(3, time); fwritePoint.WriteFeature(pFeaturePoint); System.Runtime.InteropServices.Marshal.ReleaseComObject(pFeaturePoint); //记录屏幕显示区域 IEnvelope pEnvelope = null; //生成地震烈度椭圆 //当都输入值的时候,生成椭圆 if (bL && bB && bZJ && bTransAngle) { IGraphicsContainer graphicsContainer = _MainPageLayoutControl.ActiveView.FocusMap as IGraphicsContainer; string sElementName = "zjEllipticArc"; DelectElementByName(graphicsContainer, sElementName); List <EllipticArcPro> pListEllipticArcPro = CalculatEllipticArc(pPoint, dZJ, dTransAngle); int tot = pListEllipticArcPro.Count; int iCount = 1; foreach (EllipticArcPro pEllipticArcPro in pListEllipticArcPro) { IEllipticArc pEll = new EllipticArcClass(); if (tot == 3) { pEll.PutCoordsByAngle(pEllipticArcPro.ellipseStd, pEllipticArcPro.CenterPoint, pEllipticArcPro.FromAngle, pEllipticArcPro.CentralAngle, pEllipticArcPro.rotationAngle, pEllipticArcPro.semiMajor / 100000, pEllipticArcPro.minorMajorRatio); } else { pEll.PutCoordsByAngle(pEllipticArcPro.ellipseStd, pEllipticArcPro.CenterPoint, pEllipticArcPro.FromAngle, pEllipticArcPro.CentralAngle, pEllipticArcPro.rotationAngle, pEllipticArcPro.semiMajor / 100000, pEllipticArcPro.minorMajorRatio); } IGeometry pGeo = EllipticArcTransPolygon(pEll); pGeo.SpatialReference = spatialReference; IPolygon pPloy = pGeo as IPolygon; if (iCount == 1) //第一个烈度图层 { IFeatureClass pFeatureClass8LD = pFeatureLayer8LD.FeatureClass; IFeatureClassWrite fwrite8LD = pFeatureClass8LD as IFeatureClassWrite; IFeature pFeature8LD = pFeatureClass8LD.CreateFeature(); pFeature8LD.Shape = pPloy; fwrite8LD.WriteFeature(pFeature8LD); System.Runtime.InteropServices.Marshal.ReleaseComObject(pFeature8LD); pFeature8LD = null; if (dZJ > 5.3) { iCount++; } //更新显示区域 IActiveView pAV = _MainPageLayoutControl.ActiveView.FocusMap as IActiveView; pEnvelope = pPloy.Envelope; pEnvelope.Expand(1.8, 1.8, true); pAV.Extent = pEnvelope; pAV.Refresh(); } else if (iCount == 2) { IFeatureClass pFeatureClass7LD = pFeatureLayer7LD.FeatureClass; IFeatureClassWrite fwrite7LD = pFeatureClass7LD as IFeatureClassWrite; IFeature pFeature7LD = pFeatureClass7LD.CreateFeature(); pFeature7LD.Shape = pPloy; fwrite7LD.WriteFeature(pFeature7LD); System.Runtime.InteropServices.Marshal.ReleaseComObject(pFeature7LD); pFeature7LD = null; if (tot == 3) { iCount++; } } else if (iCount == 3) { IFeatureClass pFeatureClass6LD = pFeatureLayer6LD.FeatureClass; IFeatureClassWrite fwrite6LD = pFeatureClass6LD as IFeatureClassWrite; IFeature pFeature6LD = pFeatureClass6LD.CreateFeature(); pFeature6LD.Shape = pPloy; fwrite6LD.WriteFeature(pFeature6LD); System.Runtime.InteropServices.Marshal.ReleaseComObject(pFeature6LD); pFeature6LD = null; iCount++; } } } pFeaturePoint = null; pWorkspaceEdit.StopEditOperation(); pWorkspaceEdit.StopEditing(true); this.Hide(); setFormIPoint(pPoint, textBoxLevel.Text, pEnvelope); //修改标题 IElement pElementTitle = _MainPageLayoutControl.FindElementByName("Title"); ITextElement pTextElementTitle = pElementTitle as ITextElement; string sXZQName = GetXZQName(pPoint); string sText = sXZQName + "M" + textBoxLevel.Text + "级地震震区水库分布图"; pTextElementTitle.Text = sText; MessageBox.Show("操作成功!", "提示"); }
private ISegmentCollection createSegments(Cell cell,BoostVoronoi bv,ArcConstructionMethods method,ISpatialReference spatialReference) { List<Cell> cells = bv.Cells; List<Edge> edges = bv.Edges; List<Vertex> vertices = bv.Vertices; IPoint previousEndPoint = null; ISegmentCollection segmentCollection = new PolygonClass() { SpatialReference = spatialReference }; // As per boost documentation, edges are returned in counter clockwise (CCW) rotation. // voronoi_edge_type* next() Returns the pointer to the CCW next edge within the corresponding Voronoi cell. Edges not necessarily share a common vertex (e.g. infinite edges). for (int i = cell.EdgesIndex.Count - 1; i >= 0; i--) { Edge edge = edges[cell.EdgesIndex[i]]; //If the vertex index equals -1, it means the edge is infinite. It is impossible to print the coordinates. if (!edge.IsFinite && edge.End < 0) { // this is the ending portion of a pair of infinite edges, file the previous edge with Start >= 0 Edge previous = null; for (int k = i + 1; k < cell.EdgesIndex.Count; k++) { previous = edges[cell.EdgesIndex[k]]; if (previous.End >= 0) break; previous = null; } if (previous == null) { for (int k = 0; k < i; k++) { previous = edges[cell.EdgesIndex[k]]; if (previous.End >= 0) break; previous = null; } } if (previous == null) throw new Exception("No outbound infinite edge could be found"); //Add a straight line segment Vertex start = vertices[previous.End]; IPoint FromPoint = new PointClass() { X = start.X, Y = start.Y, SpatialReference = spatialReference }; Vertex end = vertices[edge.Start]; IPoint ToPoint = new PointClass() { X = end.X, Y = end.Y, SpatialReference = spatialReference }; segmentCollection.AddSegment(new LineClass() { FromPoint = FromPoint, ToPoint = ToPoint, SpatialReference = spatialReference }); previousEndPoint = ToPoint; } else if (edge.IsFinite) { Vertex start = vertices[edge.End]; IPoint FromPoint = new PointClass() { X = start.X, Y = start.Y, SpatialReference = spatialReference }; if (previousEndPoint != null) { if ((Math.Abs(previousEndPoint.X - FromPoint.X) > 0.05 || Math.Abs(previousEndPoint.X - FromPoint.X) > 0.05)) throw new Exception("Significant change between last end point and current start point"); else FromPoint = previousEndPoint; } Vertex end = vertices[edge.Start]; IPoint ToPoint = new PointClass() { X = end.X, Y = end.Y, SpatialReference = spatialReference }; if (method == ArcConstructionMethods.Straight || edge.IsLinear) { segmentCollection.AddSegment(new LineClass() { FromPoint = FromPoint, ToPoint = ToPoint, SpatialReference = spatialReference }); previousEndPoint = ToPoint; } else { // We need three points, use start, end, mid-point between focus and directrix Cell twinCell = cells[edges[edge.Twin].Cell]; VPoint pointSite; VSegment lineSite; if (cell.ContainsPoint && twinCell.ContainsSegment) { pointSite = bv.RetrieveInputPoint(cell); lineSite = bv.RetrieveInputSegment(twinCell); } else if (cell.ContainsSegment && twinCell.ContainsPoint) { pointSite = bv.RetrieveInputPoint(twinCell); lineSite = bv.RetrieveInputSegment(cell); } else { throw new Exception("Invalid edge, curves should only be present between a point and a line"); } double scaleFactor = Convert.ToDouble(bv.ScaleFactor); IPoint aoPointSite = new Point() { X = Convert.ToDouble(pointSite.X) / scaleFactor, Y = Convert.ToDouble(pointSite.Y) / scaleFactor, SpatialReference = spatialReference }; ISegment aoLineSite = new LineClass() { FromPoint = new PointClass() { X = Convert.ToDouble(lineSite.Start.X) / scaleFactor, Y = Convert.ToDouble(lineSite.Start.Y) / scaleFactor, SpatialReference = spatialReference }, ToPoint = new PointClass() { X = Convert.ToDouble(lineSite.End.X) / scaleFactor, Y = Convert.ToDouble(lineSite.End.Y) / scaleFactor, SpatialReference = spatialReference }, SpatialReference = spatialReference }; if (method == ArcConstructionMethods.Approximate) { List<Vertex> sampledVerticed = null; try { sampledVerticed = bv.SampleCurvedEdge(edge, aoLineSite.Length / 10); } catch (FocusOnDirectixException e) { //Log any exception here is required sampledVerticed = new List<Vertex>() { start, end }; } catch (UnsolvableVertexException e) { sampledVerticed = new List<Vertex>() { start, end }; } sampledVerticed.Reverse(); List<IPoint> discretizedEdge = sampledVerticed.Select( p => new Point() { X = p.X, Y = p.Y } ).ToList<IPoint>(); IPoint prev = discretizedEdge[0]; foreach (IPoint v in discretizedEdge.Skip(1)) { segmentCollection.AddSegment(new LineClass() { FromPoint = new Point() { X = prev.X, Y = prev.Y, SpatialReference = spatialReference }, ToPoint = new Point() { X = v.X, Y = v.Y, SpatialReference = spatialReference }, SpatialReference = spatialReference }); prev = v; } previousEndPoint = discretizedEdge.Last(); } else if (method == ArcConstructionMethods.Circular) { IPoint nearPoint = ((IProximityOperator)aoLineSite).ReturnNearestPoint(aoPointSite, esriSegmentExtension.esriNoExtension); IPoint midpoint = new PointClass() { X = (nearPoint.X + aoPointSite.X) / 2, Y = (nearPoint.Y + aoPointSite.Y) / 2, SpatialReference = spatialReference }; IConstructCircularArc constArc = new CircularArcClass() { SpatialReference = spatialReference }; constArc.ConstructThreePoints(FromPoint, midpoint, ToPoint, false); ICircularArc arc = (ICircularArc)constArc; if (!arc.IsMinor) { constArc = new CircularArcClass() { SpatialReference = spatialReference }; constArc.ConstructEndPointsRadius(FromPoint, ToPoint, !arc.IsCounterClockwise, arc.Radius, true); arc = (ICircularArc)constArc; } segmentCollection.AddSegment((ISegment)arc); previousEndPoint = arc.ToPoint; } else if (method == ArcConstructionMethods.Ellipse) { IPoint nearPoint = ((IProximityOperator)aoLineSite).ReturnNearestPoint(aoPointSite, esriSegmentExtension.esriExtendTangents); nearPoint.SpatialReference = spatialReference; ILine lineToFocus = new LineClass() { FromPoint = nearPoint, ToPoint = aoPointSite, SpatialReference = spatialReference }; ILine semiMajor = new LineClass() { SpatialReference = spatialReference }; lineToFocus.QueryTangent(esriSegmentExtension.esriExtendTangentAtTo, 1, true, 100 * lineToFocus.Length, semiMajor); IPoint center = new PointClass() { X = (semiMajor.FromPoint.X + semiMajor.ToPoint.X) / 2, Y = (semiMajor.FromPoint.Y + semiMajor.ToPoint.Y) / 2, SpatialReference = spatialReference }; double minor_length = Math.Sqrt( Math.Pow(distance(semiMajor.FromPoint, ToPoint) + distance(semiMajor.ToPoint, ToPoint), 2) - Math.Pow(semiMajor.Length, 2)); IEllipticArc arc = new EllipticArcClass() { SpatialReference = spatialReference }; double rotation = lineToFocus.Angle; double from = GetAngle(center, FromPoint); arc.PutCoords(false, center, FromPoint, ToPoint, rotation, minor_length / semiMajor.Length, esriArcOrientation.esriArcMinor); segmentCollection.AddSegment((ISegment)arc); previousEndPoint = arc.ToPoint; } } } } return segmentCollection; }