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