bool evaluateTangent(InferredCurve inferredCurve, RelatedCurve curve) { //double angle = Math.Atan((inferredCurve.FromPoint.Y - inferredCurve.ToPoint.Y) / (inferredCurve.FromPoint.X - inferredCurve.ToPoint.X)); //double length = ((IProximityOperator)inferredCurve.FromPoint).ReturnDistance(inferredCurve.ToPoint); //the proposed arc chord: ILine line = new Line() { FromPoint = inferredCurve.FromPoint, ToPoint = inferredCurve.ToPoint }; //half the delta of the proposed curve would be: double halfdelta = toDegrees(Math.Asin(line.Length / 2 / curve.Radius)); IVector3D chordVector = new Vector3D() as IVector3D; chordVector.PolarSet(line.Angle, 0, 1); foreach (RelatedLine tangent in inferredCurve.TangentLines) { IVector3D tangentVector = new Vector3D() as IVector3D; tangentVector.PolarSet(ToRadians(tangent.Angle), 0, 1); bool dMatch = false; double dVectDiff = toDegrees(Math.Acos(chordVector.DotProduct(tangentVector))); if (tangent.Orientation == RelativeOrientation.From_To) dMatch = Math.Abs(dVectDiff - halfdelta) < CurveByInferenceSettings.Instance.MaxTangentLineAngleInDegrees; else if (tangent.Orientation == RelativeOrientation.To_From) dMatch = Math.Abs(dVectDiff + halfdelta) < CurveByInferenceSettings.Instance.MaxTangentLineAngleInDegrees; else if (tangent.Orientation == RelativeOrientation.From_From) dMatch = Math.Abs(dVectDiff + halfdelta) < CurveByInferenceSettings.Instance.MaxTangentLineAngleInDegrees; else if (tangent.Orientation == RelativeOrientation.To_To) dMatch = Math.Abs(dVectDiff - halfdelta) < CurveByInferenceSettings.Instance.MaxTangentLineAngleInDegrees; if (dMatch) { inferredCurve.InferredRadius = inferredCurve.TangentCurves[0].Radius; inferredCurve.InferredCenterpointID = inferredCurve.TangentCurves[0].CenterpointID; return true; } } return false; }
private static object GenerateConstructorStatment_Curve(InferredCurve curve) { StringBuilder strBuilder = new StringBuilder(); strBuilder.Append(String.Format(CreateCurve, curve.ObjectID)); strBuilder.Append(String.Join(ListJoin, (from r in curve.TangentCurves select String.Format(CreateRelatedCurve, r.ObjectID, r.Radius, r.CenterpointID, r.Orientation)).ToArray())); strBuilder.Append(CreateCurveClose); if(curve.HasValue) strBuilder.AppendFormat(AcceptedCreate, curve.InferredRadius, curve.InferredCenterpointID); strBuilder.Append(ParallelCreate); strBuilder.Append(String.Join(ListJoin, (from r in curve.ParallelCurves select String.Format(CreateCurveItem, r.ObjectID, r.Radius, r.CenterpointID, r.Orientation)).ToArray())); strBuilder.Append(ParallelCreateClose); strBuilder.Append(LineCreate); strBuilder.Append(String.Join(ListJoin, (from r in curve.TangentLines select String.Format(CreateLineItem, r.ObjectID, r.Angle, r.DeltaAngle, r.Orientation)).ToArray())); strBuilder.Append(Environment.NewLine + LineCreateClose); return strBuilder.ToString(); }
bool evaluateParallelCurves(InferredCurve inferredCurve, RelatedCurve curve) { bool bHasConfirmer = false; foreach (RelatedCurve dd in inferredCurve.ParallelCurves) { if (Math.Abs(dd.Radius - curve.Radius) < CurveByInferenceSettings.Instance.MaxRadiusDifference) { bHasConfirmer = true; break; } } if (bHasConfirmer) { inferredCurve.InferredRadius = inferredCurve.TangentCurves[0].Radius; inferredCurve.InferredCenterpointID = inferredCurve.TangentCurves[0].CenterpointID; return true; } return false; }
private bool evaluateJunctions(InferredCurve curve, List<RelatedLine> tangentLines) { //count the perpendicular lines at the start and end points of the line List<RelatedLine> startPerpendicular = tangentLines.Where(t => t.isAtStart && t.DeltaAngle > 90 - CurveByInferenceSettings.Instance.PerpendicularTolerance && t.DeltaAngle < 90 + CurveByInferenceSettings.Instance.PerpendicularTolerance).ToList(); List<RelatedLine> endPerpendicular = tangentLines.Where(t => t.isAtEnd && t.DeltaAngle > 90 - CurveByInferenceSettings.Instance.PerpendicularTolerance && t.DeltaAngle < 90 + CurveByInferenceSettings.Instance.PerpendicularTolerance).ToList(); //if there aren't any perpendicular lines if (startPerpendicular.Count == 0 && endPerpendicular.Count == 0) return true; //if both ends have perpendicular lines if (startPerpendicular.Count > 0 && endPerpendicular.Count > 0) return true; List<RelatedLine> perpendiculars = endPerpendicular; bool atStart = false; if (startPerpendicular.Count > 0 && endPerpendicular.Count == 0) { atStart = true; perpendiculars = startPerpendicular; } //determin what lines are actually present List<RelatedCurve> curves = null; List<RelatedLine> tangents = null; if (atStart) { curves = curve.TangentCurves.Where(w => w.isAtStart).ToList(); tangents = tangentLines.Where(w => w.isAtStart && w.DeltaAngle < 5).ToList(); } else { curves = curve.TangentCurves.Where(w => w.isAtEnd).ToList(); tangents = tangentLines.Where(w => w.isAtEnd && w.DeltaAngle < 5).ToList(); } //int perpendicularCount = perpendiculars.Select(w => w.DeltaAngle).Distinct().Count(); var groupsAngle = tangents.GroupBy(item => item, relatedLineComparer); //var groupsRadiusAndCP = curves.GroupBy(item => item, relatedCurveComparer).Where(group => group.Skip(1).Any()); var groupsRadiusAndCP = curves.GroupBy(item => item, relatedCurveComparer); if (groupsAngle.Count() == 1 && groupsRadiusAndCP.Count() == 0) { // only a straight line on the other side of the perpendicular return false; } else if (groupsAngle.Count() == 0 && groupsRadiusAndCP.Count() == 1) { // only a curved line on the other side of the perpendicular, so set the curve curve.InferredCenterpointID = curves[0].CenterpointID; curve.InferredRadius = curves[0].Radius; curve.TangentLines = tangentLines; return true; } //no comment, let the rest of the logic look through everything return true; }
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); }
void RefineToBestRadiusAndCenterPoint(InferredCurve inferredCurve, IFeatureClass pFabricLinesFC, IFeature pLineFeat, IPolycurve polyCurve, List<RelatedLine> tangentLines) { //only one radius found, simple case if (inferredCurve.TangentCurves.Count == 1) { //search the parallel offsets for one conformer, if found return inferredCurve.ParallelCurves = GetParallelCurveMatchFeatures(pFabricLinesFC, pLineFeat, polyCurve, ""); if (inferredCurve.ParallelCurves.Count > 0 && evaluateParallelCurves(inferredCurve, inferredCurve.TangentCurves[0])) { return; } //search the tagent lines for one conformer, if found return inferredCurve.TangentLines = tangentLines; if (inferredCurve.TangentLines.Count > 0 && evaluateTangent(inferredCurve, inferredCurve.TangentCurves[0])) { return; } } else //if there is more than one tangent curve, try to group them together { var groupsTangent = inferredCurve.TangentCurves.GroupBy(item => Math.Round(item.Radius, 2)).Where(group => group.Skip(1).Any()); var groupsTangentAndCP = inferredCurve.TangentCurves.GroupBy(item => item, relatedCurveComparer).Where(group => group.Skip(1).Any()); //System.Diagnostics.Debug.Print(groupsTangent.Count().ToString()); //System.Diagnostics.Debug.Print(groupsTangentAndCP.Count().ToString()); bool HasStartTangents = inferredCurve.TangentCurves.Any(w => w.Orientation == RelativeOrientation.To_From || w.Orientation == RelativeOrientation.To_To); bool HasEndTangents = inferredCurve.TangentCurves.Any(w => w.Orientation == RelativeOrientation.From_To || w.Orientation == RelativeOrientation.From_From); //if there is only 1 of each group, then there are no ambiguities for the tangent or the center point if (groupsTangent.Count() == 1 && groupsTangentAndCP.Count() == 1) { IGrouping<RelatedCurve, RelatedCurve> d1 = groupsTangentAndCP.ElementAt(0); //if there are curves on either side of the query feature if (HasStartTangents && HasEndTangents) { inferredCurve.InferredRadius = d1.Key.Radius; inferredCurve.InferredCenterpointID = d1.Key.CenterpointID; return; } if (inferredCurve.TangentCurves.Count > 0) { //search the parallel offsets for one conformer, if found return inferredCurve.ParallelCurves = GetParallelCurveMatchFeatures(pFabricLinesFC, pLineFeat, polyCurve, ""); if (inferredCurve.ParallelCurves.Count > 0 && evaluateParallelCurves(inferredCurve, d1.Key)) { return; } //search the tagent lines for one conformer, if found return inferredCurve.TangentLines = tangentLines; if (inferredCurve.TangentLines.Count > 0 && evaluateTangent(inferredCurve, d1.Key)) { return; } } } else if (groupsTangent.Count() == 1 && groupsTangentAndCP.Count() > 1) { //if there is only 1 tangent, but more than one center point then there are center points to merge //TODO: Add center point Merging here } if (groupsTangent.Count() > 1) { //if there is more than 1 tangent, then ...code stub if needed foreach (var value in groupsTangentAndCP) { System.Diagnostics.Debug.Print(value.Key.ToString()); } } } }
private void SelectAndZoom(InferredCurve curve, bool zoom, bool select, bool related) { IFeatureLayer fl = getLayerByLayerName(curve.LayerName); if (fl == null) MessageBox.Show(String.Format("The layer {0} could not be found", curve.LayerName)); List<int> oids = new List<int>(); oids.Add(curve.ObjectID); if (related) { oids.AddRange(curve.ParallelCurves.Select(w => w.ObjectID)); oids.AddRange(curve.TangentCurves.Select(w => w.ObjectID)); oids.AddRange(curve.TangentLines.Select(w => w.ObjectID)); } IEnvelope extent = null; if (select) ArcMap.Document.FocusMap.ClearSelection(); IFeatureCursor featureCursor = fl.FeatureClass.GetFeatures(oids.ToArray(), true); IFeature feature = null; while ((feature = featureCursor.NextFeature()) != null) { if (extent == null) extent = feature.Shape.Envelope; else extent.Union(feature.Shape.Envelope); if (select) ArcMap.Document.FocusMap.SelectFeature(fl, feature); Marshal.ReleaseComObject(feature); } if (zoom) { ZoomTo(extent); } else { ArcMap.Document.ActivatedView.Refresh(); } }