private bool UpdateCircularArcValues(IFeatureClass LineTable, IQueryFilter QueryFilter, bool Unversioned, IDictionary<int, InferredCurve> CurveLookup, myProgessor progressor, Dictionary<int, int> MaxSequenceCache) { IFeature pLineFeat = null; IFeatureBuffer buffer = null; IFeatureCursor pLineCurs = null; IFeatureCursor pRadialCur = null; IFeatureCursor maxCursor = null; IDataStatistics dataStatistics = null; IGeometryFactory3 geometryFactory = new GeometryEnvironmentClass(); IGeometry geometry = new PolylineClass(); geometryFactory.CreateEmptyGeometryByType(LineTable.ShapeType, out geometry); IGeometryDef geometryDef = LineTable.Fields.get_Field(LineTable.FindField(LineTable.ShapeFieldName)).GeometryDef; if (geometryDef.HasZ) { IZAware zAware = (IZAware)(geometry); zAware.ZAware = true; } if (geometryDef.HasM) { IMAware mAware = (IMAware)(geometry); mAware.MAware = true; } try { CurveByInferenceSettings.FieldPositions positions = new CurveByInferenceSettings.FieldPositions((ITable)LineTable); buffer = LineTable.CreateFeatureBuffer(); pLineCurs = LineTable.Update(QueryFilter, false); pRadialCur = LineTable.Insert(false); while ((pLineFeat = pLineCurs.NextFeature()) != null) { //loop through all of the given lines, and update centerpoint ids, radius, and arc length values if (!progressor.Continue()) return false; progressor.Step(); InferredCurve curveInfo = CurveLookup[pLineFeat.OID]; pLineFeat.set_Value(positions.RadiusFieldIdx, curveInfo.InferredRadius); pLineFeat.set_Value(positions.CenterpointIDFieldIdx, curveInfo.InferredCenterpointID); IFeature feature = pLineFeat as IFeature; double length = 0; if (feature != null) { IPolyline polyline = feature.ShapeCopy as IPolyline; if (polyline != null) { length = ((IProximityOperator)polyline.FromPoint).ReturnDistance(polyline.ToPoint); pLineFeat.set_Value(positions.ArcLengthFieldIdx, length); Marshal.ReleaseComObject(polyline); } } if (Unversioned) pLineCurs.UpdateFeature(pLineFeat); else pLineFeat.Store(); //fine the max sequence value int maxSequence = -1; if (MaxSequenceCache.ContainsKey(curveInfo.Parcel)) { maxSequence = MaxSequenceCache[curveInfo.Parcel]; } else { maxCursor = LineTable.Search(new QueryFilter() { SubFields = String.Format("{0}, {1}, {2}", LineTable.OIDFieldName, CurveByInferenceSettings.Instance.SequenceFieldName, CurveByInferenceSettings.Instance.ParcelIDFieldName), WhereClause = String.Format("{0} = {1}", CurveByInferenceSettings.Instance.ParcelIDFieldName, curveInfo.Parcel) }, true); int seqenceIdx = maxCursor.Fields.FindField(CurveByInferenceSettings.Instance.SequenceFieldName); IRow maxFeat = null; while ((maxFeat = maxCursor.NextFeature()) != null) { maxSequence = Math.Max((int)maxFeat.get_Value(seqenceIdx), maxSequence); Marshal.ReleaseComObject(maxFeat); } Marshal.ReleaseComObject(maxCursor); MaxSequenceCache.Add(curveInfo.Parcel, maxSequence); dataStatistics = null; maxCursor = null; } if (maxSequence <= 0) throw new Exception("Failed to find max sequence value"); //the chord bearing double featureBearing = (double)pLineFeat.get_Value(positions.BearingFieldIdx); //half the delta of the proposed curve would be: double halfdelta = toDegrees(Math.Asin(length / 2 / curveInfo.InferredRadius.Value)); //perpendicular to the chord double perpendicular = (curveInfo.InferredRadius.Value > 0) ? featureBearing + 90 : featureBearing - 90; if (perpendicular > 360) perpendicular = perpendicular - 360; else if (perpendicular < 0) perpendicular = perpendicular + 360; for (int i = 0; i < 2; i++) { buffer.set_Value(positions.ParcelIDFieldIdx, curveInfo.Parcel); buffer.set_Value(positions.ToPointFieldIdx, curveInfo.InferredCenterpointID); buffer.set_Value(positions.CategoryFieldIdx, 4); buffer.set_Value(positions.SequenceFieldIdx, ++maxSequence); buffer.set_Value(positions.TypeFieldIdx, 0); buffer.set_Value(positions.DistanceFieldIdx, curveInfo.InferredRadius); buffer.set_Value(positions.HistoricalFieldIdx, 0); buffer.set_Value(positions.LineParametersFieldIdx, 0); buffer.set_Value(positions.DensifyTypeIdx, 0); buffer.set_Value(positions.SystemStartDateFieldIdx, pLineFeat.get_Value(positions.SystemStartDateFieldIdx)); buffer.Shape = geometry; if (i == 0) // startpoing { buffer.set_Value(positions.FromPointFieldIdx, pLineFeat.get_Value(positions.FromPointFieldIdx)); buffer.set_Value(positions.BearingFieldIdx, perpendicular + halfdelta); } else //endpoint { buffer.set_Value(positions.FromPointFieldIdx, pLineFeat.get_Value(positions.ToPointFieldIdx)); buffer.set_Value(positions.BearingFieldIdx, perpendicular - halfdelta); } pRadialCur.InsertFeature(buffer); } MaxSequenceCache[curveInfo.Parcel] = maxSequence; Marshal.ReleaseComObject(pLineFeat); } return true; } catch (COMException ex) { messageBox.Show(String.Format("Problem updating circular arc: {0} ({1})", ex.Message, ex.ErrorCode)); return false; } finally { if(pLineCurs != null) Marshal.ReleaseComObject(pLineCurs); if(buffer != null) Marshal.ReleaseComObject(buffer); if(pRadialCur != null) Marshal.ReleaseComObject(pRadialCur); if(dataStatistics != null) Marshal.ReleaseComObject(dataStatistics); if (maxCursor != null) Marshal.ReleaseComObject(maxCursor); if (geometry != null) Marshal.FinalReleaseComObject(geometry); if (geometryFactory != null) Marshal.FinalReleaseComObject(geometryFactory); } }
public void FindCurves(String Name, IFeatureClass pFabricLinesFC, ISelectionSet selSet, string whereClause, myProgessor progressor) { CurveByInferenceSettings.FieldPositions positions = new CurveByInferenceSettings.FieldPositions((ITable)pFabricLinesFC); if (!positions.ValidCheckFields) { messageBox.Show(string.Format("One or more of the following fields are missing ({0}, {1})", CurveByInferenceSettings.Instance.RadiusFieldName, CurveByInferenceSettings.Instance.CenterpointIDFieldName)); } IQueryFilter qFilter = new QueryFilter(); if (String.IsNullOrEmpty(whereClause)) { qFilter.WhereClause = "CenterPointID is null and Radius is null"; } else { qFilter.WhereClause = string.Concat(whereClause, " and CenterPointID is null and Radius is null"); } IFeatureCursor cursor = null; if (selSet != null) { ICursor c; ISelectionSet subset = selSet.Select(qFilter, esriSelectionType.esriSelectionTypeIDSet, esriSelectionOption.esriSelectionOptionNormal, null); progressor.setStepProgressorProperties(subset.Count, String.Format("Layer {0}: Evaluating Selected Features", Name)); subset.Search(null, true, out c); cursor = (IFeatureCursor)c; } else { progressor.setStepProgressorProperties(((ITable)pFabricLinesFC).RowCount(qFilter), String.Format("Layer {0}: Evaluating Features", Name)); cursor = pFabricLinesFC.Search(qFilter, true); } //ISelectionSet pSelSet = pFabricLinesFC.Select(qFilter, esriSelectionType.esriSelectionTypeIDSet, esriSelectionOption.esriSelectionOptionNormal, null); //progressor.setStepProgressorProperties(pSelSet.Count, String.Format("Layer {0}: Evaluating Features", Name)); //ICursor cursor = null; //pSelSet.Search(null, false, out cursor); IFeature pLineFeat = null; while ((pLineFeat = (IFeature)cursor.NextFeature() as IFeature) != null) { if (!progressor.Continue()) break; progressor.Step(); if (!Curves.Any(w => w.ObjectID == pLineFeat.OID)) { IGeometry pGeom = pLineFeat.ShapeCopy; ISegmentCollection pSegColl = pGeom as ISegmentCollection; ISegment pSeg = null; if (pSegColl != null && pSegColl.SegmentCount == 1) { pSeg = pSegColl.get_Segment(0); } else { if (pSegColl == null) messageBox.Show(String.Format("The shape for objectid {0} could not be converted to a segement collection.", pLineFeat.OID)); //todo: but for now, only deals with single segment short segments Marshal.ReleaseComObject(pLineFeat); continue; } //if the geometry is a circular arc and the attributes reflect that, move on to the next feature //obsolete, filter is pushed to database //if (pSeg is ICircularArc) //{ // object dVal1 = pLineFeat.get_Value(idxRADIUS); // object dVal2 = pLineFeat.get_Value(idxCENTERPTID); // if (!(dVal1 is DBNull) && !(dVal2 is DBNull)) // { // Marshal.ReleaseComObject(pLineFeat); // continue; // } //} //query near lines List<RelatedLine> tangentLines; List<RelatedCurve> sCurveInfoFromNeighbours = GetTangentCurveMatchFeatures(pFabricLinesFC, pLineFeat, (IPolycurve)pGeom, "", positions.RadiusFieldIdx, positions.CenterpointIDFieldIdx, pSeg.Length, out tangentLines); if(sCurveInfoFromNeighbours.Count > 0) //if (HasTangentCurveMatchFeatures(pFabricLinesFC, (IPolycurve)pGeom, "", pSeg.Length, out iFoundTangent, ref sCurveInfoFromNeighbours)) { InferredCurve curve = new InferredCurve(pLineFeat.OID, Name, sCurveInfoFromNeighbours); IPolyline polyLine = (IPolyline)pGeom; curve.FromPoint = polyLine.FromPoint; curve.ToPoint = polyLine.ToPoint; //evaluated the position of any tangent lines, and determines if there is a junction situation. If there is, it will: // Retrun true with curve.Accepted set // Return true without curve.Accepted set // Return false (this indicates that the junction has been used to verify that this segemnt should not have a curve) if (evaluateJunctions(curve, tangentLines)) { //junction couldn't eliminate the curve, so return it Curves.Add(curve); curve.PropertyChanged += new PropertyChangedEventHandler(curve_PropertyChanged); curve.Parcel = (int)pLineFeat.get_Value(positions.ParcelIDFieldIdx); if (!curve.HasValue) //if the junction logic didn't set the curve { //check to see if one of the tange curves overlap if (curve.TangentCurves[0].Orientation == RelativeOrientation.Same || curve.TangentCurves[0].Orientation == RelativeOrientation.Reverse) { curve.InferredRadius = curve.TangentCurves[0].Radius; curve.InferredCenterpointID = curve.TangentCurves[0].CenterpointID; } else { //check radial and tangent lines (both need a single centerpoint and radius tangent curve (check done in function) RefineToBestRadiusAndCenterPoint(curve, pFabricLinesFC, pLineFeat, (IPolycurve)pGeom, tangentLines); } } //if the curve has an accepted curve (ie, it's a candidate to be changed), record the parcel id //if (curve.Accepted != null) // affectedParcels.Add(); //cache the parcel so it can be looked up later } } } Marshal.ReleaseComObject(pLineFeat); } Marshal.ReleaseComObject(cursor); Total = Curves.Count; Inferred = Curves.Count(w => w.Action == UpdateAction.Update); }