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