Example #1
0
        private ArrayList ProcessFeature(IFeature test, SegmentCollectionIndex index,
			double searchRadius, double aspectRatio, bool canDefer, bool canExcept)
        {
            if (test == null || test.Shape == null || test.Shape.IsEmpty)
                return null;

            ArrayList theReturn = new ArrayList();

            IDataset theDataset = (IDataset)test.Table;

            IGeometry theTestShape = test.ShapeCopy;
            theTestShape.Project(SpatialReferenceHelper.BCAlbersSpatialReference);
            ISegmentCollection theSegColl = (ISegmentCollection)theTestShape;
            ISegment theSegment;

            for (int i = 0; i < theSegColl.SegmentCount; i++)
            {
                theSegment = theSegColl.get_Segment(i);
                int theNeatlineOID;
                double dist1 = index.get_MinimumDistance(theSegment.FromPoint, out theNeatlineOID);
                if (dist1 <= searchRadius)
                {
                    double dist2 = index.get_MinimumDistance(theSegment.ToPoint, out theNeatlineOID);
                    if (dist2 <= searchRadius)
                    {
                        if (Math.Abs(dist1 - dist2) < theSegment.Length / aspectRatio)
                        {
                            // Error point will be 1/2 way along segment
                            IPolyline thePolyline = new PolylineClass();
                            thePolyline.Project(SpatialReferenceHelper.BCAlbersSpatialReference);
                            ((ISegmentCollection)thePolyline).AddSegment(theSegment, ref this._missing, ref this._missing);
                            thePolyline.Project(SpatialReferenceHelper.GeographicReference);

                            IPoint theErrorPoint = new PointClass();
                            thePolyline.QueryPoint(esriSegmentExtension.esriNoExtension, 0.5, true, theErrorPoint);

                            DataQualityError theError = new DataQualityError(this.Name, canDefer, canExcept);
                            theError.Location = theErrorPoint;

                            // If it's in the smallest 10% of the search radius, mark high severity
                            // 50%, medium
                            double avgDist = (dist1 + dist2) / 2;
                            if (avgDist <= searchRadius / 10)
                                theError.Severity = 1;
                            else if (avgDist <= searchRadius / 2)
                                theError.Severity = 2;
                            else
                                theError.Severity = 3;

                            theError.Description = "Line segment co-linear with neatline";

                            ExtendedInfo theInfo = new ExtendedInfo();

                            theInfo.AddProperty("Feature class", theDataset.Name);
                            if (test.HasOID)
                                theInfo.AddProperty("Feature ID", test.OID.ToString());
                            theInfo.AddProperty("Neatline Feature ID", theNeatlineOID.ToString());
                            theInfo.AddProperty("Distance", String.Format("{0:0.## metres}", avgDist));
                            theInfo.AddProperty("From point x", thePolyline.FromPoint.X.ToString());
                            theInfo.AddProperty("From point y", thePolyline.FromPoint.Y.ToString());
                            theInfo.AddProperty("To point x", thePolyline.ToPoint.X.ToString());
                            theInfo.AddProperty("To point y", thePolyline.ToPoint.Y.ToString());

                            theError.ExtendedData = theInfo.WriteXML();
                            //this.LogMessage(theError.ExtendedData);
                            theReturn.Add(theError);
                        }
                    }
                }
            }
            return theReturn;
        }
Example #2
0
        public override int Execute(string logfileName)
        {
            this.InitLogging(logfileName);
            this.LogMessage(this.Name + " QA test execution started.");

            int currentOid = -1;
            bool bProblemsRunning = false;

            try
            {
                this.LogMessage(this.Name + " Parameters:");
                for (int i = 0; i < this.ParameterCount; i++)
                    this.LogMessage(this.get_ParameterText(i) + ": " + this.get_ParameterValue(i));

                this.ClearErrors();

                int index = this.FindParameter("search-radius");
                double searchRadius = Math.Abs((double)((ParameterInfo)this._params[index]).ParamValue);

                index = this.FindParameter("aspect-ratio-limit");
                double aspectRatio = Math.Abs((double)((ParameterInfo)this._params[index]).ParamValue);
                if (aspectRatio <= 1)
                {
                    aspectRatio = 10;
                    this.LogMessage("Segment length to distance ratio set under 1.0, using 10 instead.");
                }

                index = this.FindParameter(ParameterInfo.PARAM_CANDEFER);
                bool canDefer = (bool)((ParameterInfo)this._params[index]).ParamValue;
                index = this.FindParameter(ParameterInfo.PARAM_CANEXCEPT);
                bool canExcept = (bool)((ParameterInfo)this._params[index]).ParamValue;
                index = this.FindParameter("limit-neatline-index");
                bool limitNeatline = (bool)((ParameterInfo)this._params[index]).ParamValue;

                // Convert gap limits to metres
                UnitsParameterInfo theUnits = (UnitsParameterInfo)this._params[this.FindParameter("search-units")];
                IUnitConverter theConverter = new UnitConverterClass();
                searchRadius = theConverter.ConvertUnits(searchRadius, theUnits.ParamValueInUnits, esriUnits.esriMeters);

                IFeatureLayer theNeatlineLayer = this.NeatlineLayer;
                if (theNeatlineLayer == null)
                {
                    this.LogMessage("Missing valid neatline layer. Exiting Execute.");
                    bProblemsRunning = true;
                }
                else
                {
                    // Create index of neatline segments
                    this.LogMessage("Building neatline index");

                    // Calc cell size by taking some segment lengths
                    double sum = 0;
                    int segCount = 0;
                    IFeatureCursor theNLCursor = this.NeatlineLayer.Search(null, true);
                    IFeature theNeatline = theNLCursor.NextFeature();

                    while (theNeatline != null)
                    {
                        IGeometry theGeometry = theNeatline.Shape;
                        theGeometry.Project(SpatialReferenceHelper.BCAlbersSpatialReference);
                        ISegmentCollection theSegColl = (ISegmentCollection)theGeometry;
                        for (int i = 0; i < theSegColl.SegmentCount; i++)
                        {
                            sum += theSegColl.get_Segment(i).Length;
                            segCount++;
                        }
                        theNeatline = theNLCursor.NextFeature();
                        if (segCount > 100)
                            break;
                    }
                    Marshal.ReleaseComObject(theNLCursor);
                    theNLCursor = null;

                    double cellsize = (sum / segCount) * 5;
                    this.LogMessage("Cellsize: (" + sum + " / " + segCount + ") = " + cellsize);

                    // Determine the bounding env for the features to analyze
                    // If this is significantly smaller than the bounds of the neatline
                    // layer, this will save time building the cache
                    ISpatialFilter theSF = null;
                    if (limitNeatline)
                    {
                        IEnvelope theAOI = null;
                        for (int layerIdx = 0; layerIdx < this.LayerCount; layerIdx++)
                        {
                            IFeatureLayer theFLayer = this.get_Layer(layerIdx);
                            IFeatureClass theFClass = theFLayer.FeatureClass;
                            if (theFLayer != theNeatlineLayer
                                && this.SupportsGeometryType(theFClass.ShapeType))
                            {
                                if (this.ConstrainToSelection)
                                {
                                    IFeatureCursor theFCursor;
                                    ICursor theCursor;
                                    IFeatureSelection theFSel = (IFeatureSelection)theFLayer;
                                    theFSel.SelectionSet.Search(null, true, out theCursor);
                                    theFCursor = (IFeatureCursor)theCursor;
                                    IFeature theFeature = theFCursor.NextFeature();
                                    while (theFeature != null)
                                    {
                                        if (theFeature.Shape != null && theFeature.Shape.IsEmpty == false)
                                        {
                                            if (theAOI != null)
                                                theAOI.Union(theFeature.Shape.Envelope);
                                            else
                                                theAOI = theFeature.Shape.Envelope;
                                        }
                                        theFeature = theFCursor.NextFeature();
                                    }
                                    Marshal.ReleaseComObject(theFCursor);
                                }
                                else
                                {
                                    if (theAOI != null)
                                        theAOI.Union(theFLayer.AreaOfInterest);
                                    else
                                        theAOI = theFLayer.AreaOfInterest;
                                }
                            }
                        }

                        theSF = new SpatialFilterClass();
                        theSF.Geometry = theAOI;
                        theSF.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
                    }

                    SegmentCollectionIndex theIndex = new SegmentCollectionIndex(cellsize);
                    theNLCursor = this.NeatlineLayer.Search(theSF, true);
                    theNeatline = theNLCursor.NextFeature();
                    while (theNeatline != null)
                    {
                        ISegmentCollection theSegColl = theNeatline.Shape as ISegmentCollection;
                        for (int i = 0; i < theSegColl.SegmentCount; i++)
                        {
                            IndexSegment theSegment = new IndexSegment(theNeatline.OID, theSegColl.get_Segment(i));
                            theIndex.AddSegment(theSegment);
                        }
                        theNeatline = theNLCursor.NextFeature();
                    }

                    for (int layerIdx = 0; layerIdx < this.LayerCount; layerIdx++)
                    {
                        IFeatureLayer theFLayer = this.get_Layer(layerIdx);
                        IFeatureClass theFClass = theFLayer.FeatureClass;
                        IDataset theDataset = (IDataset)theFClass;

                        if (theFLayer != theNeatlineLayer
                            && this.SupportsGeometryType(theFClass.ShapeType))
                        {
                            this.LogMessage("Detecting neatline artifacts in featureclass " + theDataset.Name);

                            int nFeatures = 0;

                            IFeatureCursor theFCursor = null;
                            IFeatureSelection theFSel = (IFeatureSelection)theFLayer;

                            if (this.ConstrainToSelection)
                            {
                                this.LogMessage("Constraining analysis to selected features.");
                                ICursor theCursor;
                                theFSel.SelectionSet.Search(null, true, out theCursor);
                                theFCursor = (IFeatureCursor)theCursor;
                                nFeatures = theFSel.SelectionSet.Count;
                            }
                            else
                            {
                                theFCursor = theFClass.Search(null, true);
                                nFeatures = theFClass.FeatureCount(null);
                            }

                            this.LogMessage("Number of features to process: " + nFeatures);

                            int count = 0;
                            int countIncrement = Math.Max(1, nFeatures / 10);

                            IFeature theFeature = theFCursor.NextFeature();

                            while (theFeature != null)
                            {
                                if (theFeature.HasOID)
                                    currentOid = theFeature.OID; // for error trapping and debugging

                                ArrayList theList = this.ProcessFeature(theFeature, theIndex,
                                    searchRadius, aspectRatio, canDefer, canExcept);

                                if (theList != null)
                                {
                                    foreach (DataQualityError dqe in theList)
                                        this._errors.Add(dqe);
                                }

                                if (++count % countIncrement == 0)
                                {
                                    this.LogMessage("Processed " + count + " polygons...");
                                }
                                theFeature = theFCursor.NextFeature();
                            }

                            Marshal.ReleaseComObject(theFCursor);
                        }
                    }
                }

                this.LogMessage("Number of errors found: " + this.ErrorCount);
                this.LogMessage("Test " + this.Name + " successful.");
            }
            catch (Exception ex)
            {
                this.LogMessage("Exception caught: \n" + ex.Message + "\n" + ex.StackTrace.ToString());
                this.LogMessage("id of the current polygon: " + currentOid);
                return -1;
            }
            finally
            {
                this.StopLogging();
            }

            if (bProblemsRunning)
                return -1;

            return this.ErrorCount;
        }