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 UpdateCurves(ICadastralFabric pCadFabric, IFeatureClass pFabricLinesFC, IEnumerable<InferredCurve> curvesToUpdate, myProgessor progressor) { IEnumerable<InferredCurve> updateCurves = (from InferredCurve c in curvesToUpdate where c.Action == UpdateAction.Update select c); bool bIsFileBasedGDB = false; bool bIsUnVersioned = false; bool bUseNonVersionedDelete = false; IWorkspace pWS = m_pEd != null ? m_pEd.EditWorkspace : ((IDataset)pFabricLinesFC).Workspace; if (!SetupEditEnvironment(pWS, pCadFabric, m_pEd, out bIsFileBasedGDB, out bIsUnVersioned, out bUseNonVersionedDelete)) { messageBox.Show("The editing environment could not be initialized"); return; } #region Create Cadastral Job string sTime = ""; if (!bIsUnVersioned && !bIsFileBasedGDB) { //see if parcel locks can be obtained on the selected parcels. First create a job. DateTime localNow = DateTime.Now; sTime = Convert.ToString(localNow); ICadastralJob pJob = new CadastralJob(); pJob.Name = sTime; pJob.Owner = System.Windows.Forms.SystemInformation.UserName; pJob.Description = "Convert lines to curves"; try { Int32 jobId = pCadFabric.CreateJob(pJob); } catch (COMException ex) { if (ex.ErrorCode == (int)fdoError.FDO_E_CADASTRAL_FABRIC_JOB_ALREADY_EXISTS) { messageBox.Show("Job named: '" + pJob.Name + "', already exists"); } else { messageBox.Show(ex.Message); } return; } } #endregion #region Test for Edit Locks ICadastralFabricLocks pFabLocks = (ICadastralFabricLocks)pCadFabric; //only need to get locks for parcels that have lines that are to be changed ILongArray affectedParcels = new LongArrayClass(); IFIDSet parcelFIDs = new FIDSet(); foreach (int i in updateCurves.Select(w => w.Parcel).Distinct()) { parcelFIDs.Add(i); affectedParcels.Add(i); } if (!bIsUnVersioned && !bIsFileBasedGDB) { pFabLocks.LockingJob = sTime; ILongArray pLocksInConflict = null; ILongArray pSoftLcksInConflict = null; if (!bIsFileBasedGDB) progressor.setStepProgressorProperties(0, "Testing for edit locks on parcels..."); try { pFabLocks.AcquireLocks(affectedParcels, true, ref pLocksInConflict, ref pSoftLcksInConflict); } catch (COMException pCOMEx) { if (pCOMEx.ErrorCode == (int)fdoError.FDO_E_CADASTRAL_FABRIC_JOB_LOCK_ALREADY_EXISTS || pCOMEx.ErrorCode == (int)fdoError.FDO_E_CADASTRAL_FABRIC_JOB_CURRENTLY_EDITED) { messageBox.Show("Edit Locks could not be acquired on all selected parcels."); // since the operation is being aborted, release any locks that were acquired pFabLocks.UndoLastAcquiredLocks(); } else messageBox.Show(pCOMEx.Message + Environment.NewLine + Convert.ToString(pCOMEx.ErrorCode)); return; } } #endregion if (m_pEd != null && m_pEd.EditState == esriEditState.esriStateEditing) { try { m_pEd.StartOperation(); } catch { m_pEd.AbortOperation();//abort any open edit operations and try again m_pEd.StartOperation(); } } else { //this code is extecuted by the tests, only executed against a file gdb IWorkspaceEdit wsEdit = (IWorkspaceEdit)pWS; wsEdit.StartEditing(false); wsEdit.StartEditOperation(); } if (bUseNonVersionedDelete) { if (!StartEditing(pWS, bIsUnVersioned)) { messageBox.Show("Couldn't start an edit session"); return; } } ICadastralFabricSchemaEdit2 pSchemaEd = (ICadastralFabricSchemaEdit2)pCadFabric; pSchemaEd.ReleaseReadOnlyFields((ITable)pFabricLinesFC, esriCadastralFabricTable.esriCFTLines); //release for edits // m_pEd.StartOperation(); updateValues(updateCurves, progressor, pFabricLinesFC, bIsUnVersioned); ICadastralFabricRegeneration pRegenFabric = new CadastralFabricRegenerator(); #region regenerator enum // enum esriCadastralRegeneratorSetting // esriCadastralRegenRegenerateGeometries = 1 // esriCadastralRegenRegenerateMissingRadials = 2, // esriCadastralRegenRegenerateMissingPoints = 4, // esriCadastralRegenRemoveOrphanPoints = 8, // esriCadastralRegenRemoveInvalidLinePoints = 16, // esriCadastralRegenSnapLinePoints = 32, // esriCadastralRegenRepairLineSequencing = 64, // esriCadastralRegenRepairPartConnectors = 128 // By default, the bitmask member is 0 which will only regenerate geometries. // (equivalent to passing in regeneratorBitmask = 1) #endregion //pRegenFabric.CadastralFabric = pCadFabric; //pRegenFabric.RegeneratorBitmask = 7; //pRegenFabric.RegenerateParcels(parcelFIDs, false, progressor.cancelTracker); if (m_pEd != null) { m_pEd.StopOperation("Insert missing circular arc information."); } else { //this code is extecuted by the tests, only executed against a file gdb IWorkspaceEdit wsEdit = (IWorkspaceEdit)pWS; wsEdit.StartEditOperation(); wsEdit.StopEditing(false); } }
private void updateValues(IEnumerable<InferredCurve> updateCurves, myProgessor progressor, IFeatureClass pFabricLinesFC, bool bIsUnVersioned) { Dictionary<int, int> MaxSequenceCache = new Dictionary<int, int>(); IQueryFilter m_pQF = new QueryFilter(); //Slice the list into sets that will fit into an in list int curveCount = updateCurves.Count(); progressor.setStepProgressorProperties(curveCount, "Updating geometries"); for (var i = 0; i < curveCount; i += 995) { Dictionary<int, InferredCurve> curvesSlice = updateCurves.Skip(i).Take(995).ToDictionary(w => w.ObjectID); if (!progressor.Continue()) return; m_pQF.WhereClause = String.Format("{0} IN ({1})", pFabricLinesFC.OIDFieldName, String.Join(",", (from oid in curvesSlice.Keys select oid.ToString()).ToArray())); UpdateCircularArcValues(pFabricLinesFC, m_pQF, bIsUnVersioned, curvesSlice, progressor, MaxSequenceCache); } }
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); }