User Tools

Site Tools


source_code_desktopeditionsample_topologyvalidation_cs_120904.zip

Table of Contents

Source Code DesktopEditionSample TopologyValidation CS 120904.zip

InputFeatureLayerType.cs

using System;
namespace TopologyValidation
{
    public enum InputFeatureLayerType
    {
        First = 0,
        Second = 1
    }
}

LineAndPolygonInputLayersTopologyTestCase.cs

using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public abstract class LineAndPolygonInputLayersTopologyTestCase : TwoInputLayersTopologyTestCase
    {
        protected LineAndPolygonInputLayersTopologyTestCase()
            : this("LineAndPolygonInputLayersTopologyTestCase")
        { }
        protected LineAndPolygonInputLayersTopologyTestCase(string name)
            : base(name)
        {
            SecondInputFeatureLayer.ZoomLevelSet = FirstInputFeatureLayer.ZoomLevelSet;
            TestCaseInputType = TestCaseInputType.LineAndPolygon;
        }
        protected override void AddInputShapeCore(BaseShape shape)
        {
            WellKnownType type = shape.GetWellKnownType();
            if (type == WellKnownType.Line || type == WellKnownType.Multiline)
            {
                FirstInputFeatureLayer.InternalFeatures.Add(shape.GetFeature());
            }
            else if (type == WellKnownType.Polygon || type == WellKnownType.Multipolygon)
            {
                SecondInputFeatureLayer.InternalFeatures.Add(shape.GetFeature());
            }
        }
    }
}

LinesEndPointMustBeCoveredByPointsTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class LinesEndPointMustBeCoveredByPointsTopologyTestCase : PointAndLineInputLayersTopologyTestCase
    {
        public LinesEndPointMustBeCoveredByPointsTopologyTestCase()
            : this("LinesEndPointMustBeCoveredByPointsTopologyTestCase")
        { }
        public LinesEndPointMustBeCoveredByPointsTopologyTestCase(string name)
            : base(name)
        { }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.LinesEndPointMustBeCoveredByPoints(SecondInputFeatureLayer.InternalFeatures, FirstInputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (Feature shape in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(shape);
            }
        }
    }
}

LinesMustBeCoveredByBoundaryOfPolygonsTopologyTestCase.cs

using System;
using System.Collections.Generic;
using System.Text;
using ThinkGeo.MapSuite.Core;
using System.Collections.ObjectModel;
namespace TopologyValidation
{
    public class LinesMustBeCoveredByBoundaryOfPolygonsTopologyTestCase : LineAndPolygonInputLayersTopologyTestCase
    {
        public LinesMustBeCoveredByBoundaryOfPolygonsTopologyTestCase()
            : this("LinesMustBeCoveredByBoundaryOfPolygonsTopologyTestCase")
        { }
        public LinesMustBeCoveredByBoundaryOfPolygonsTopologyTestCase(string name)
            : base(name)
        { }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.LinesMustBeCoveredByBoundaryOfPolygons(FirstInputFeatureLayer.InternalFeatures, SecondInputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

LinesMustBeCoveredByFeatureClassOfLinesTopologyTestCase.cs

using System;
using System.Collections.Generic;
using System.Text;
using ThinkGeo.MapSuite.Core;
using System.Collections.ObjectModel;
namespace TopologyValidation
{
    public class LinesMustBeCoveredByFeatureClassOfLinesTopologyTestCase : TwoInputLayersTopologyTestCase
    {
        public LinesMustBeCoveredByFeatureClassOfLinesTopologyTestCase()
            : this("LinesMustBeCoveredByFeatureClassOfLinesTopologyTestCase")
        { }
        public LinesMustBeCoveredByFeatureClassOfLinesTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.LineAndLine;
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.LinesMustBeCoveredByFeatureClassOfLines(SecondInputFeatureLayer.InternalFeatures, FirstInputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

LinesMustBeLargerThanClusterToleranceTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class LinesMustBeLargerThanClusterToleranceTopologyTestCase : OneInputLayerTopologyTestCase
    {
        private double tolerance = 30;
        private InMemoryFeatureLayer assistantLayer;
        public InMemoryFeatureLayer AssistantLayer
        {
            get { return assistantLayer; }
        }
        public LinesMustBeLargerThanClusterToleranceTopologyTestCase()
            : this("LinesMustBeLargerThanClusterToleranceTopologyTestCase")
        { }
        public LinesMustBeLargerThanClusterToleranceTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.Line;
            InputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.FromArgb(70, 0, 0, 255), 2, true);
            InputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(20, 0, 0, 255), GeoColor.FromArgb(255, 0, 0, 255), 2);
            OutputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.FromArgb(200, GeoColor.StandardColors.Green), 2, true);
            OutputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(102, 0, 0, 255), GeoColor.FromArgb(255, 0, 0, 255), 2);
            OutputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.SimpleColors.Transparent, 10);
            assistantLayer = new InMemoryFeatureLayer();
            assistantLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(20, 255, 255, 255), GeoColor.FromArgb(70, 0, 0, 0));
            assistantLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimplePointStyle(PointSymbolType.Circle, GeoColor.SimpleColors.Red, 5);
            assistantLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            this.Layers.Add(assistantLayer);
        }
        public double Tolerance
        {
            get
            {
                return tolerance;
            }
            set
            {
                tolerance = value;
            }
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> lineShapes = TopologyValidator.LinesMustBeLargerThanClusterTolerance(InputFeatureLayer.InternalFeatures, tolerance);
            OutputFeatureLayer.InternalFeatures.Clear();
            assistantLayer.InternalFeatures.Clear();
            foreach (Feature lineShape in lineShapes)
            {
                OutputFeatureLayer.InternalFeatures.Add(lineShape);
                foreach (Vertex vertex in ((LineShape)lineShape.GetShape()).Vertices)
                {
                    EllipseShape ellipseShape = new EllipseShape(new PointShape(vertex), tolerance);
                    assistantLayer.InternalFeatures.Add(new Feature(ellipseShape));
                    Feature pointFeature = new Feature(vertex);
                    assistantLayer.InternalFeatures.Add(pointFeature);
                }
            }
        }
        protected override void ClearCore()
        {
            base.ClearCore();
            assistantLayer.InternalFeatures.Clear();
        }
    }
}

LinesMustBeSinglePartTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class LinesMustBeSinglePartTopologyTestCase : OneInputLayerTopologyTestCase
    {
        public LinesMustBeSinglePartTopologyTestCase()
            : this("LinesMustBeSinglePartTopologyTestCase")
        { }
        public LinesMustBeSinglePartTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.Line;
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.LinesMustBeSinglePart(InputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

LinesMustNotHaveDanglesTopologyTestCase.cs

using System;
using System.Collections.Generic;
using System.Text;
using ThinkGeo.MapSuite.Core;
using System.Collections.ObjectModel;
namespace TopologyValidation
{
    public class LinesMustNotHaveDanglesTopologyTestCase : OneInputLayerTopologyTestCase
    {
        public LinesMustNotHaveDanglesTopologyTestCase()
            : this("LinesMustNotHaveDanglesTopologyTestCase")
        { }
        public LinesMustNotHaveDanglesTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.Line;
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.LinesMustNotHaveDangles(InputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

LinesMustNotHavePseudonodesTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class LinesMustNotHavePseudonodesTopologyTestCase : OneInputLayerTopologyTestCase
    {
        public LinesMustNotHavePseudonodesTopologyTestCase()
            : this("LinesMustNotHavePseudonodesTopologyTestCase")
        { }
        public LinesMustNotHavePseudonodesTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.Line;
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.LinesMustNotHavePseudonodes(InputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

LinesMustNotIntersectOrTouchInteriorTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class LinesMustNotIntersectOrTouchInteriorTopologyTestCase : OneInputLayerTopologyTestCase
    {
        public LinesMustNotIntersectOrTouchInteriorTopologyTestCase()
            : this("LinesMustNotIntersectOrTouchInteriorTopologyTestCase")
        { }
        public LinesMustNotIntersectOrTouchInteriorTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.Line;
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.LinesMustNotIntersectOrTouchInterior(InputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

LinesMustNotIntersectTopologyTestCase.cs

using ThinkGeo.MapSuite.Core;
using System.Collections.ObjectModel;
namespace TopologyValidation
{
    public class LinesMustNotIntersectTopologyTestCase : OneInputLayerTopologyTestCase
    {
        public LinesMustNotIntersectTopologyTestCase()
            : this("LinesMustNotIntersectTopologyTestCase")
        { }
        public LinesMustNotIntersectTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.Line;
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.LinesMustNotIntersect(InputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

LinesMustNotOverlapTopologyTestCase.cs

using System;
using System.Collections.Generic;
using System.Text;
using ThinkGeo.MapSuite.Core;
using System.Collections.ObjectModel;
namespace TopologyValidation
{
    public class LinesMustNotOverlapTopologyTestCase : OneInputLayerTopologyTestCase
    {
        public LinesMustNotOverlapTopologyTestCase()
            : this("LinesMustNotOverlapTopologyTestCase")
        { }
        public LinesMustNotOverlapTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.Line;
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.LinesMustNotOverlap(InputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

LinesMustNotOverlapWithLinesTopologyTestCase.cs

using ThinkGeo.MapSuite.Core;
using System.Collections.ObjectModel;
namespace TopologyValidation
{
    public class LinesMustNotOverlapWithLinesTopologyTestCase : TwoInputLayersTopologyTestCase
    {
        public LinesMustNotOverlapWithLinesTopologyTestCase()
            : this("LinesMustNotOverlapWithLinesTopologyTestCase")
        { }
        public LinesMustNotOverlapWithLinesTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.LineAndLine;
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = new Collection<Feature>();
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.LinesMustNotOverlapWithLines(FirstInputFeatureLayer.InternalFeatures, SecondInputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

LinesMustNotSelfIntersectTopologyTestCase.cs

using System.Collections.ObjectModel;
using System.Xml;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class LinesMustNotSelfIntersectTopologyTestCase : OneInputLayerTopologyTestCase
    {
        public LinesMustNotSelfIntersectTopologyTestCase()
            : this("LinesMustNotSelfIntersectTopologyTestCase")
        { }
        public LinesMustNotSelfIntersectTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.Line;
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> errorShapes = null;
            if (!LoadingFromShapeFile)
            {
                errorShapes = TopologyValidator.LinesMustNotSelfIntersect(InputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in errorShapes)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
        protected override void FromXmlCore(XmlNode node)
        {
            BaseShape.GeometryLibrary = GeometryLibrary.Managed;
            base.FromXmlCore(node);
            BaseShape.GeometryLibrary = GeometryLibrary.Unmanaged;
        }
    }
}

LinesMustNotSelfOverlapTopologyTestCase.cs

using ThinkGeo.MapSuite.Core;
using System.Collections.ObjectModel;
namespace TopologyValidation
{
    public class LinesMustNotSelfOverlapTopologyTestCase : OneInputLayerTopologyTestCase
    {
        public LinesMustNotSelfOverlapTopologyTestCase()
            : this("LinesMustNotSelfOverlapTopologyTestCase")
        { }
        public LinesMustNotSelfOverlapTopologyTestCase(string name)
            : base(name)
        {
            BaseShape.GeometryLibrary = GeometryLibrary.Managed;
            TestCaseInputType = TestCaseInputType.Line;
        }
        protected override void GenerateTestResultCore()
        {
            BaseShape.GeometryLibrary = GeometryLibrary.Unmanaged;
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.LinesMustNotSelfOverlap(InputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

MainForm.cs

using System;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Data;
using System.IO;
using System.Management;
using System.Text;
using System.Windows.Forms;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.DesktopEdition;
using System.Xml;
using System.Reflection;
namespace TopologyValidation
{
    public partial class MainForm : Form
    {
        TopologyTestCase currentTopologyTestCase;
        Collection<TopologyTestCase> loadedTopologyTestCases = new Collection<TopologyTestCase>();
        string testCasesFilePath = ConfigurationManager.AppSettings.Get("DefaultTestCasesFilePath");
        private bool fromEvent = false;
        public MainForm()
        {
            InitializeComponent();
        }
        private void MainForm_Load(object sender, EventArgs e)
        {
            SetToolTip();
            winformsMap1.MapUnit = GeographyUnit.Meter;
            winformsMap1.ZoomLevelSnapping = ZoomLevelSnappingMode.None;
            LoadTestCases();
            winformsMap1.CurrentScale = new ZoomLevelSet().ZoomLevel10.Scale;
            currentTopologyTestCase = new PolygonsMustNotOverlapTopologyTestCase();
            winformsMap1.TrackOverlay.TrackEnded += new EventHandler<TrackEndedTrackInteractiveOverlayEventArgs>(TrackOverlay_TrackEnded);
            if (listboxNames.Items.Count > 0)
            {
                listboxNames.SelectedIndex = 0;
                txtCaseDescription.Text = loadedTopologyTestCases[listboxNames.SelectedIndex].Description;
            }
            cmbTopologyRules.SelectedIndex = 0;
            listboxNames.SelectedIndex = 0;
        }
        private void SetToolTip()
        {
            toolTip1.SetToolTip(btnRunTestCase, "Run Current Case");
            toolTip1.SetToolTip(btnImportExportWKT, "Import/Export WKT");
            toolTip1.SetToolTip(btnSaveTestCase, "Save Case");
            toolTip1.SetToolTip(btnSaveTestCaseInCurrentExtent, "Save Case Within Current Extent");
            toolTip1.SetToolTip(btnDeleteTestCase, "Delete Current Case");
            toolTip1.SetToolTip(btnTrackNormal, "Normal");
            toolTip1.SetToolTip(btnTrackPoint, "Point");
            toolTip1.SetToolTip(btnTrackLine, "Line");
            toolTip1.SetToolTip(btnTrackCoveredLine, "Covered line");
            toolTip1.SetToolTip(btnTrackPolygon, "Polygon");
            toolTip1.SetToolTip(btnTrackCoveredPolygon, "Covered polygon");
            toolTip1.SetToolTip(btnTrackDelete, "Clear");
        }
        private void cmbTopologyRules_SelectedIndexChanged(object sender, EventArgs e)
        {
            winformsMap1.TrackOverlay.TrackShapeLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(102, 0, 0, 255), GeoColor.FromArgb(255, 0, 0, 255), 2);
            currentTopologyTestCase = GetTestCaseInstance(cmbTopologyRules.SelectedItem.ToString());
            if (!fromEvent)
            {
                listboxNames.SelectedIndex = -1;
            }
            else
            {
                fromEvent = false;
            }
            UpdateEditButtons();
            if (currentTopologyTestCase == null)
            {
                MessageBox.Show("The test case is not implemented");
            }
            ClearAll();
        }
        private void UpdateEditButtons()
        {
            btnTrackLine.Enabled = false;
            btnTrackPoint.Enabled = false;
            btnTrackPolygon.Enabled = false;
            btnTrackCoveredLine.Enabled = false;
            btnTrackCoveredPolygon.Enabled = false;
            switch (currentTopologyTestCase.TestCaseInputType)
            {
                case TestCaseInputType.Line:
                    EnableEditButtons(btnTrackLine);
                    break;
                case TestCaseInputType.LineAndLine:
                    EnableEditButtons(btnTrackLine, btnTrackCoveredLine);
                    break;
                case TestCaseInputType.LineAndPolygon:
                    EnableEditButtons(btnTrackLine, btnTrackPolygon);
                    break;
                case TestCaseInputType.Point:
                    EnableEditButtons(btnTrackPoint);
                    break;
                case TestCaseInputType.PointAndLine:
                    EnableEditButtons(btnTrackPoint, btnTrackLine);
                    break;
                case TestCaseInputType.PointAndPolygon:
                    EnableEditButtons(btnTrackPoint, btnTrackPolygon);
                    break;
                case TestCaseInputType.Polygon:
                    EnableEditButtons(btnTrackPolygon);
                    break;
                case TestCaseInputType.PolygonAndPolygon:
                    EnableEditButtons(btnTrackPolygon, btnTrackCoveredPolygon);
                    break;
                case TestCaseInputType.PointAndLineAndPolygon:
                default:
                    EnableEditButtons(btnTrackPoint, btnTrackLine, btnTrackPolygon);
                    break;
            }
        }
        private void EnableEditButtons(params Button[] buttons)
        {
            foreach (var item in buttons)
            {
                item.Enabled = true;
            }
        }
        private void btnTopologyResult_Click(object sender, System.EventArgs e)
        {
            try
            {
                if (currentTopologyTestCase is LinesMustBeLargerThanClusterToleranceTopologyTestCase)
                {
                    ToleranceForm form = new ToleranceForm();
                    if (form.ShowDialog() == DialogResult.OK)
                    {
                        ((LinesMustBeLargerThanClusterToleranceTopologyTestCase)currentTopologyTestCase).Tolerance = form.Tolerance;
                    }
                    else
                    {
                        return;
                    }
                }
                else if (currentTopologyTestCase is PolygonsMustBeLargerThanClusterToleranceTopologyTestCase)
                {
                    ToleranceForm form = new ToleranceForm();
                    if (form.ShowDialog() == DialogResult.OK)
                    {
                        ((PolygonsMustBeLargerThanClusterToleranceTopologyTestCase)currentTopologyTestCase).Tolerance = form.Tolerance;
                    }
                    else
                    {
                        return;
                    }
                }
                currentTopologyTestCase.GenerateTestResult();
                winformsMap1.TrackOverlay.TrackShapeLayer.InternalFeatures.Clear();
                currentTopologyTestCase.Draw(winformsMap1);
                string wkt = currentTopologyTestCase.GetOutputInString();
                if (string.IsNullOrEmpty(wkt))
                {
                    MessageBox.Show(string.Format("No result returned and no WKT is exported."));
                }
                else
                {
                    Clipboard.SetDataObject(wkt);
                    MessageBox.Show(string.Format("The WKT of {0} return records has been copied to Clipboard", currentTopologyTestCase.OutputFeatureLayer.InternalFeatures.Count), "Note");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        private void btnImportSingleWKT_Click(object sender, EventArgs e)
        {
            ShapesWktLoader wktImporter = new ShapesWktLoader(currentTopologyTestCase);
            if (wktImporter.ShowDialog() == DialogResult.OK)
            {
                ClearAll();
                if (currentTopologyTestCase is OneInputLayerTopologyTestCase)
                {
                    foreach (var item in wktImporter.Features[0])
                    {
                        ((OneInputLayerTopologyTestCase)currentTopologyTestCase).InputFeatureLayer.InternalFeatures.Add(item);
                    }
                }
                else if (currentTopologyTestCase is TwoInputLayersTopologyTestCase)
                {
                    foreach (var item in wktImporter.Features[0])
                    {
                        ((TwoInputLayersTopologyTestCase)currentTopologyTestCase).FirstInputFeatureLayer.InternalFeatures.Add(item);
                    }
                    foreach (var item in wktImporter.Features[1])
                    {
                        ((TwoInputLayersTopologyTestCase)currentTopologyTestCase).SecondInputFeatureLayer.InternalFeatures.Add(item);
                    }
                }
                winformsMap1.CurrentExtent = currentTopologyTestCase.GetBoundingBox();
                winformsMap1.CurrentExtent.ScaleUp(30);
                currentTopologyTestCase.OutputFeatureLayer.InternalFeatures.Clear();
                currentTopologyTestCase.Draw(winformsMap1);
            }
        }
        private void btnSaveToXML_Click(object sender, EventArgs e)
        {
            SaveTestCaseDialog saveTestCaseDialog = new SaveTestCaseDialog(currentTopologyTestCase.GetType().Name, "", testCasesFilePath, null);
            if (saveTestCaseDialog.ShowDialog() == DialogResult.OK)
            {
                currentTopologyTestCase.Name = saveTestCaseDialog.TestCaseName;
                currentTopologyTestCase.Description = saveTestCaseDialog.Description;
                currentTopologyTestCase.ToXml(testCasesFilePath + "
" + saveTestCaseDialog.TestCaseName);
                LoadTestCases();
            }
        }
        private void btnDeleteTestCase_Click(object sender, EventArgs e)
        {
            if (listboxNames.SelectedValue != null)
            {
                if (MessageBox.Show("Are you sure you want to delete it?", "Delete Test Case", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    string name = ((DataRowView)listboxNames.SelectedItem).Row.ItemArray[0].ToString();
                    if (File.Exists(testCasesFilePath + "
" + name + ".xml"))
                    {
                        File.Delete(testCasesFilePath + "
" + name + ".xml");
                    }
                    LoadTestCases();
                }
            }
        }
        private void btnClear_Click(object sender, System.EventArgs e)
        {
            ClearAll();
        }
        private void btnSaveCaseInCurrentExtent_Click(object sender, EventArgs e)
        {
            SaveTestCaseDialog saveTestCaseDialog = new SaveTestCaseDialog(currentTopologyTestCase.GetType().Name, "", testCasesFilePath, winformsMap1.CurrentExtent);
            if (saveTestCaseDialog.ShowDialog() == DialogResult.OK)
            {
                TopologyTestCase topologyTestCase = currentTopologyTestCase.GenerateTestCaseWithinExtent(winformsMap1.CurrentExtent);
                topologyTestCase.Name = saveTestCaseDialog.TestCaseName;
                topologyTestCase.Description = saveTestCaseDialog.Description;
                topologyTestCase.ToXml(testCasesFilePath + "
" + saveTestCaseDialog.TestCaseName);
                LoadTestCases();
            }
        }
        private void lbTestCases_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listboxNames.SelectedValue != null && listboxNames.SelectedValue.ToString() != typeof(System.Data.DataRowView).ToString())
            {
                fromEvent = true;
                txtCaseDescription.Text = loadedTopologyTestCases[listboxNames.SelectedIndex].Description;
                ClearAll();
                TopologyTestCase testCase = loadedTopologyTestCases[listboxNames.SelectedIndex];
                winformsMap1.CurrentExtent = testCase.GetBoundingBox();
                winformsMap1.CurrentExtent.ScaleUp(30);
                string typeName = testCase.GetType().Name.Replace("TopologyTestCase", "");
                int count = 0;
                foreach (var item in cmbTopologyRules.Items)
                {
                    if (item.ToString() == typeName)
                    {
                        break;
                    }
                    count++;
                }
                cmbTopologyRules.SelectedIndex = count;
                testCase.Draw(winformsMap1);
                currentTopologyTestCase = testCase.Clone();
            }
        }
        private void TrackButton_Click(object sender, System.EventArgs e)
        {
            Button button = sender as Button;
            var twoInputTestCase = currentTopologyTestCase as TwoInputLayersTopologyTestCase;
            if (button != null)
            {
                switch (button.Name)
                {
                    case "btnTrackNormal":
                        winformsMap1.TrackOverlay.TrackMode = TrackMode.None;
                        break;
                    case "btnTrackPoint":
                        winformsMap1.TrackOverlay.TrackMode = TrackMode.Point;
                        break;
                    case "btnTrackLine":
                        winformsMap1.TrackOverlay.TrackMode = TrackMode.Line;
                        if (btnTrackCoveredLine.Enabled)
                        {
                            twoInputTestCase.InputFeatureLayerType = InputFeatureLayerType.First;
                            winformsMap1.TrackOverlay.TrackShapeLayer.InternalFeatures.Clear();
                            winformsMap1.TrackOverlay.TrackShapeLayer.ZoomLevelSet = twoInputTestCase.FirstInputFeatureLayer.ZoomLevelSet;
                            twoInputTestCase.Draw(winformsMap1);
                        }
                        else
                        {
                            if (twoInputTestCase != null)
                            {
                                winformsMap1.TrackOverlay.TrackShapeLayer.ZoomLevelSet = twoInputTestCase.FirstInputFeatureLayer.ZoomLevelSet;
                            }
                            else
                            {
                                winformsMap1.TrackOverlay.TrackShapeLayer.ZoomLevelSet = ((OneInputLayerTopologyTestCase)currentTopologyTestCase).InputFeatureLayer.ZoomLevelSet;
                            }
                        }
                        break;
                    case "btnTrackCoveredLine":
                        twoInputTestCase.InputFeatureLayerType = InputFeatureLayerType.Second;
                        winformsMap1.TrackOverlay.TrackMode = TrackMode.Line;
                        winformsMap1.TrackOverlay.TrackShapeLayer.InternalFeatures.Clear();
                        winformsMap1.TrackOverlay.TrackShapeLayer.ZoomLevelSet = twoInputTestCase.SecondInputFeatureLayer.ZoomLevelSet;
                        twoInputTestCase.Draw(winformsMap1);
                        break;
                    case "btnTrackPolygon":
                        winformsMap1.TrackOverlay.TrackMode = TrackMode.Polygon;
                        if (btnTrackCoveredPolygon.Enabled)
                        {
                            twoInputTestCase.InputFeatureLayerType = InputFeatureLayerType.First;
                            winformsMap1.TrackOverlay.TrackShapeLayer.InternalFeatures.Clear();
                            winformsMap1.TrackOverlay.TrackShapeLayer.ZoomLevelSet = twoInputTestCase.FirstInputFeatureLayer.ZoomLevelSet;
                            twoInputTestCase.Draw(winformsMap1);
                        }
                        else
                        {
                            if (twoInputTestCase != null)
                            {
                                winformsMap1.TrackOverlay.TrackShapeLayer.ZoomLevelSet = twoInputTestCase.FirstInputFeatureLayer.ZoomLevelSet;
                            }
                            else
                            {
                                winformsMap1.TrackOverlay.TrackShapeLayer.ZoomLevelSet = ((OneInputLayerTopologyTestCase)currentTopologyTestCase).InputFeatureLayer.ZoomLevelSet;
                            }
                        }
                        break;
                    case "btnTrackCoveredPolygon":
                        twoInputTestCase.InputFeatureLayerType = InputFeatureLayerType.Second;
                        winformsMap1.TrackOverlay.TrackMode = TrackMode.Polygon;
                        winformsMap1.TrackOverlay.TrackShapeLayer.InternalFeatures.Clear();
                        winformsMap1.TrackOverlay.TrackShapeLayer.ZoomLevelSet = twoInputTestCase.SecondInputFeatureLayer.ZoomLevelSet;
                        twoInputTestCase.Draw(winformsMap1);
                        break;
                    case "btnTrackDelete":
                        int lastIndex = winformsMap1.EditOverlay.EditShapesLayer.InternalFeatures.Count - 1;
                        if (lastIndex >= 0)
                        {
                            winformsMap1.EditOverlay.EditShapesLayer.InternalFeatures.RemoveAt(lastIndex);
                            winformsMap1.EditOverlay.CalculateAllControlPoints();
                        }
                        winformsMap1.Refresh(winformsMap1.EditOverlay);
                        break;
                    default:
                        winformsMap1.TrackOverlay.TrackMode = TrackMode.None;
                        break;
                }
            }
        }
        private void TrackOverlay_TrackEnded(object sender, TrackEndedTrackInteractiveOverlayEventArgs e)
        {
            currentTopologyTestCase.AddInputShape(e.TrackShape);
        }
        private void ClearAll()
        {
            winformsMap1.EditOverlay.EditShapesLayer.InternalFeatures.Clear();
            winformsMap1.TrackOverlay.TrackShapeLayer.InternalFeatures.Clear();
            winformsMap1.Overlays.Clear();
            winformsMap1.Refresh();
            currentTopologyTestCase.Clear();
            winformsMap1.TrackOverlay.TrackMode = TrackMode.None;
        }
        private void LoadTestCases()
        {
            loadedTopologyTestCases.Clear();
            listboxNames.DataSource = null;
            listboxNames.Items.Clear();
            if (Directory.Exists(testCasesFilePath))
            {
                Collection<TopologyTestCase> testCases = LoadTestCases(testCasesFilePath);
                DataTable dt = new DataTable();
                dt.Columns.Add(new DataColumn("name", typeof(string)));
                dt.Columns.Add(new DataColumn("id", typeof(string)));
                dt.Columns.Add(new DataColumn("description", typeof(string)));
                foreach (TopologyTestCase testCase in testCases)
                {
                    DataRow dr = dt.NewRow();
                    dr["name"] = testCase.Name;
                    dr["id"] = testCase.Id;
                    dr["description"] = testCase.Description;
                    dt.Rows.Add(dr);
                    loadedTopologyTestCases.Add(testCase);
                }
                listboxNames.DataSource = dt;
                listboxNames.DisplayMember = "name";
                listboxNames.ValueMember = "id";
            }
        }
        private Collection<string> GetTestCases()
        {
            Assembly assembly = Assembly.LoadFrom("TopologyValidation.exe");
            Collection<string> testCases = new Collection<string>();
            Type[] types = assembly.GetTypes();
            foreach (var item in types)
            {
                if (item.Name.EndsWith("TestCase") && item.Name != "TopologyTestCase")
                {
                    testCases.Add(item.FullName);
                }
            }
            return testCases;
        }
        public TopologyTestCase GetTestCaseInstance(string typeName)
        {
            Collection<string> testCases = GetTestCases();
            typeName = "TopologyValidation." + typeName + "TopologyTestCase";
            if (testCases.Contains(typeName))
            {
                return (TopologyTestCase)Activator.CreateInstance(Type.GetType(typeName));
            }
            return null;
        }
        public Collection<TopologyTestCase> LoadTestCases(string path)
        {
            Collection<TopologyTestCase> testCases = new Collection<TopologyTestCase>();
            DirectoryInfo dirInfo = new DirectoryInfo(path);
            foreach (var item in dirInfo.GetFiles("*.xml"))
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(item.FullName);
                XmlNode rootNode = doc.SelectSingleNode("//Case");
                Collection<string> topologyTestCases = GetTestCases();
                XmlNode nodeTypeName = rootNode.SelectSingleNode("./TypeName");
                TopologyTestCase topologyTestCase = null;
                if (topologyTestCases.Contains(nodeTypeName.InnerText))
                {
                    topologyTestCase = (TopologyTestCase)Activator.CreateInstance(Type.GetType(nodeTypeName.InnerText));
                }
                topologyTestCase.FromXml(rootNode);
                testCases.Add(topologyTestCase);
            }
            return testCases;
        }
    }
}

OneInputLayerTopologyTestCase.cs

using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Xml;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.DesktopEdition;
namespace TopologyValidation
{
    public abstract class OneInputLayerTopologyTestCase : TopologyTestCase
    {
        private string shapePathFileName;
        private InMemoryFeatureLayer inputFeatureLayer;
        public InMemoryFeatureLayer InputFeatureLayer
        {
            get { return inputFeatureLayer; }
        }
        public string ShapePathFileName
        {
            get { return shapePathFileName; }
            set { shapePathFileName = value; }
        }
        protected OneInputLayerTopologyTestCase()
            : this("OneInputLayerTopologyTestCase")
        { }
        protected OneInputLayerTopologyTestCase(string name)
            : base(name)
        {
            inputFeatureLayer = new InMemoryFeatureLayer();
            inputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(102, 0, 0, 255), GeoColor.FromArgb(255, 0, 0, 255), 2);
            inputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.FromArgb(102, 0, 0, 255), 2, true);
            inputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.FromArgb(102, 0, 0, 255), 12);
            inputFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            Layers = new Collection<InMemoryFeatureLayer>();
            Layers.Add(inputFeatureLayer);
            Layers.Add(OutputFeatureLayer);
        }
        protected override void AddInputShapeCore(BaseShape shape)
        {
            inputFeatureLayer.InternalFeatures.Add(shape.GetFeature());
        }
        protected override void FromXmlCore(XmlNode node)
        {
            Collection<Feature> inputFeatures = new Collection<Feature>();
            Collection<Feature> outputFeatures = new Collection<Feature>();
            XmlNode nodeTypeName = node.SelectSingleNode("./TypeName");
            XmlNode nodeName = node.SelectSingleNode("./Name");
            XmlNode nodeDescription = node.SelectSingleNode("./Description");
            XmlNode nodeInput = node.SelectSingleNode("./Input");
            XmlNode nodeID = node.SelectSingleNode("./ID");
            XmlNodeList nodesWKT = nodeInput.SelectNodes("./WKT");
            foreach (XmlNode nodeShape in nodesWKT)
            {
                string wkt = nodeShape.InnerText;
                inputFeatures.Add(new Feature(wkt));
            }
            XmlNode nodeOutput = node.SelectSingleNode("./Output");
            nodesWKT = nodeOutput.SelectNodes("./WKT");
            foreach (XmlNode nodeShape in nodesWKT)
            {
                string wkt = nodeShape.InnerText;
                outputFeatures.Add(new Feature(wkt));
            }
            this.Name = nodeName.InnerText;
            this.Id = nodeID.InnerText;
            this.Description = nodeDescription.InnerText;
            foreach (Feature feature in inputFeatures)
            {
                this.InputFeatureLayer.InternalFeatures.Add(feature);
            }
            foreach (Feature feature in outputFeatures)
            {
                this.OutputFeatureLayer.InternalFeatures.Add(feature);
            }
        }
        protected override void ToXmlCore(string path)
        {
            XmlDocument doc = new XmlDocument();
            int count = 1;
            string tempPath = path + ".xml";
            while (File.Exists(tempPath))
            {
                tempPath = path + "_" + count + ".xml";
                count++;
            }
            XmlElement caseNode = doc.CreateElement("Case");
            doc.AppendChild(caseNode);
            XmlElement typeNameNode = doc.CreateElement("TypeName");
            typeNameNode.InnerText = this.GetType().ToString();
            caseNode.AppendChild(typeNameNode);
            XmlElement idNode = doc.CreateElement("ID");
            idNode.InnerText = Guid.NewGuid().ToString();
            caseNode.AppendChild(idNode);
            XmlElement nameNode = doc.CreateElement("Name");
            nameNode.InnerText = Name + (count > 1 ? "_" + (count - 1) : "");
            caseNode.AppendChild(nameNode);
            XmlElement desNode = doc.CreateElement("Description");
            desNode.InnerText = Description;
            caseNode.AppendChild(desNode);
            XmlElement inNode = doc.CreateElement("Input");
            caseNode.AppendChild(inNode);
            foreach (var feature in InputFeatureLayer.InternalFeatures)
            {
                XmlElement wktNode = doc.CreateElement("WKT");
                wktNode.InnerText = feature.GetWellKnownText();
                inNode.AppendChild(wktNode);
            }
            XmlElement outNode = doc.CreateElement("Output");
            caseNode.AppendChild(outNode);
            foreach (var feature in OutputFeatureLayer.InternalFeatures)
            {
                XmlElement wktNode = doc.CreateElement("WKT");
                wktNode.InnerText = feature.GetWellKnownText();
                outNode.AppendChild(wktNode);
            }
            doc.Save(tempPath);
        }
        protected override void ClearCore()
        {
            base.ClearCore();
            shapePathFileName = string.Empty;
            inputFeatureLayer.InternalFeatures.Clear();
        }
        protected override RectangleShape GetBoundingBoxCore()
        {
            RectangleShape boundingBox;
            if (!LoadingFromShapeFile)
            {
                InputFeatureLayer.Open();
                boundingBox = InputFeatureLayer.GetBoundingBox();
                InputFeatureLayer.Close();
            }
            else
            {
                ShapeFileFeatureLayer shapeFileFeatureLayer = new ShapeFileFeatureLayer(shapePathFileName);
                shapeFileFeatureLayer.Open();
                boundingBox = shapeFileFeatureLayer.GetBoundingBox();
                shapeFileFeatureLayer.Close();
            }
            return boundingBox;
        }
        protected override void DrawCore(WinformsMap winformsMap)
        {
            LayerOverlay layerOverlay = null;
            if (!LoadingFromShapeFile)
            {
                layerOverlay = new LayerOverlay();
                foreach (Layer layer in Layers)
                {
                    layerOverlay.Layers.Add(layer);
                }
            }
            else
            {
                ShapeFileFeatureLayer.BuildIndexFile(ShapePathFileName, BuildIndexMode.DoNotRebuild);
                ShapeFileFeatureLayer shapeFileFeatureLayer = new ShapeFileFeatureLayer(ShapePathFileName);
                shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(102, 0, 0, 255), GeoColor.FromArgb(255, 0, 0, 255), 2);
                shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.FromArgb(102, 0, 0, 255), 2, true);
                shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.FromArgb(102, 0, 0, 255), 12);
                shapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
                layerOverlay = new LayerOverlay();
                layerOverlay.Layers.Add(shapeFileFeatureLayer);
                layerOverlay.Layers.Add(OutputFeatureLayer);
                winformsMap.CurrentExtent = GetBoundingBox();
            }
            winformsMap.Overlays.Clear();
            winformsMap.Overlays.Add(layerOverlay);
            winformsMap.Refresh();
        }
        protected override TopologyTestCase CloneCore()
        {
            OneInputLayerTopologyTestCase newObject = (OneInputLayerTopologyTestCase)Activator.CreateInstance(GetType());
            for (int i = 0; i < Layers.Count; i++)
            {
                for (int j = 0; j < Layers[i].InternalFeatures.Count; j++)
                {
                    newObject.Layers[i].InternalFeatures.Add(Layers[i].InternalFeatures[j]);
                }
            }
            return newObject;
        }
        protected override TopologyTestCase GenerateTestCaseWithinExtentCore(RectangleShape extent)
        {
            if (!OutputFeatureLayer.IsOpen)
            {
                OutputFeatureLayer.Open();
            }
            Collection<Feature> outputFeatures = OutputFeatureLayer.QueryTools.GetFeaturesInsideBoundingBox(extent, ReturningColumnsType.NoColumns);
            Collection<Feature> inputFeatures = null;
            if (!LoadingFromShapeFile)
            {
                if (!InputFeatureLayer.IsOpen)
                {
                    InputFeatureLayer.Open();
                }
                inputFeatures = InputFeatureLayer.QueryTools.GetFeaturesInsideBoundingBox(extent, ReturningColumnsType.NoColumns);
            }
            else
            {
                ShapeFileFeatureLayer shapeFileFeatureLayer = new ShapeFileFeatureLayer(ShapePathFileName);
                shapeFileFeatureLayer.Open();
                inputFeatures = shapeFileFeatureLayer.QueryTools.GetFeaturesInsideBoundingBox(extent, ReturningColumnsType.NoColumns);
                shapeFileFeatureLayer.Close();
            }
            OneInputLayerTopologyTestCase topologyTestCase = (OneInputLayerTopologyTestCase)Activator.CreateInstance(GetType());
            foreach (Feature feature in outputFeatures)
            {
                topologyTestCase.OutputFeatureLayer.InternalFeatures.Add(feature);
            }
            foreach (Feature feature in inputFeatures)
            {
                topologyTestCase.InputFeatureLayer.InternalFeatures.Add(feature);
            }
            return topologyTestCase;
        }
    }
}

PointAndLineInputLayersTopologyTestCase.cs

using System;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public abstract class PointAndLineInputLayersTopologyTestCase : TwoInputLayersTopologyTestCase
    {
        protected PointAndLineInputLayersTopologyTestCase()
            : this("PointAndLineInputLayersTopologyTestCase")
        { }
        protected PointAndLineInputLayersTopologyTestCase(string name)
            : base(name)
        {
            SecondInputFeatureLayer.ZoomLevelSet = FirstInputFeatureLayer.ZoomLevelSet;
            TestCaseInputType = TestCaseInputType.PointAndLine;
        }
        protected override void AddInputShapeCore(BaseShape shape)
        {
            WellKnownType type = shape.GetWellKnownType();
            if (type == WellKnownType.Point || type == WellKnownType.Multipoint)
            {
                FirstInputFeatureLayer.InternalFeatures.Add(shape.GetFeature());
            }
            else if (type == WellKnownType.Line || type == WellKnownType.Multiline)
            {
                SecondInputFeatureLayer.InternalFeatures.Add(shape.GetFeature());
            }
            else
            {
                throw new Exception("The input shape is wrong");
            }
        }
    }
}

PointAndPolygonInputLayersTopologyTestCase.cs

using System;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public abstract class PointAndPolygonInputLayersTopologyTestCase : TwoInputLayersTopologyTestCase
    {
        protected PointAndPolygonInputLayersTopologyTestCase()
            : this("PointAndPolygonInputLayersTopologyTestCase")
        { }
        protected PointAndPolygonInputLayersTopologyTestCase(string name)
            : base(name)
        {
            SecondInputFeatureLayer.ZoomLevelSet = FirstInputFeatureLayer.ZoomLevelSet;
            TestCaseInputType = TestCaseInputType.PointAndPolygon;
        }
        protected override void AddInputShapeCore(BaseShape shape)
        {
            WellKnownType type = shape.GetWellKnownType();
            if (type == WellKnownType.Point || type == WellKnownType.Multipoint)
            {
                FirstInputFeatureLayer.InternalFeatures.Add(shape.GetFeature());
            }
            else if (type == WellKnownType.Polygon || type == WellKnownType.Multipolygon)
            {
                SecondInputFeatureLayer.InternalFeatures.Add(shape.GetFeature());
            }
            else
            {
                throw new Exception("The input shape is wrong");
            }
        }
    }
}

SaveTestCaseDialog.cs

using System;
using System.IO;
using System.Windows.Forms;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public partial class SaveTestCaseDialog : Form
    {
        public string Description { get; set; }
        public string TestCaseName { get; set; }
        public SaveTestCaseDialog(string currentTopologyCaseName, string description, string folder, RectangleShape currentExtent)
        {
            InitializeComponent();
            this.TestCaseName = GetSplittedName(currentTopologyCaseName.Replace("TopologyTestCase", ""));
            this.Description = description;
            string path = folder + "
" + TestCaseName;
            int count = 1;
            string tempPath = path + ".xml";
            while (File.Exists(tempPath))
            {
                tempPath = path + "_" + count + ".xml";
                count++;
            }
            txtName.Text = this.TestCaseName + (count - 1 > 0 ? ("_" + (count - 1)) : "");
            txtDescription.Text = this.Description;
            if (txtName.Text.Trim() == string.Empty)
            {
                txtName.Text = "New Test Case";
            }
            if (txtDescription.Text.Trim() == string.Empty)
            {
                txtDescription.Text = String.Format("{2}{3}. Created at {0} {1}.", DateTime.Now.ToLongTimeString(), DateTime.Now.ToLongDateString(), GetSplittedName(currentTopologyCaseName), currentExtent == null ? "" : " Within Extent(" + currentExtent.ToString() + ")");
            }
        }
        private static string GetSplittedName(string name)
        {
            string result = "";
            int lastIndex = 0;
            for (int i = 0; i < name.Length; i++)
            {
                if (Char.IsUpper(name[i]))
                {
                    result = result + " " + name.Substring(lastIndex, i - lastIndex);
                    lastIndex = i;
                }
            }
            result = result + " " + name.Substring(lastIndex);
            return result.Trim();
        }
        private void btnOK_Click(object sender, EventArgs e)
        {
            this.TestCaseName = txtName.Text;
            this.Description = txtDescription.Text;
            this.DialogResult = System.Windows.Forms.DialogResult.OK;
            this.Close();
        }
        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
            this.Close();
        }
        private void CreateTestCaseMessage_Load(object sender, EventArgs e)
        {
            txtName.SelectAll();
        }
    }
}

ShapesWktLoader.cs

using System;
using System.Collections.ObjectModel;
using System.Text;
using System.Windows.Forms;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public partial class ShapesWktLoader : Form
    {
        private bool isTwoInput;
        Collection<Collection<Feature>> features;
        private string wkt1;
        private string wkt2;
        public Collection<Collection<Feature>> Features
        {
            get { return features; }
        }
        public ShapesWktLoader(TopologyTestCase testCase)
        {
            InitializeComponent();
            if (testCase is OneInputLayerTopologyTestCase)
            {
                isTwoInput = false;
                wkt1 = GetWktFromFeatureLayer(((OneInputLayerTopologyTestCase)testCase).InputFeatureLayer);
            }
            else if (testCase is TwoInputLayersTopologyTestCase)
            {
                isTwoInput = true;
                wkt1 = GetWktFromFeatureLayer(((TwoInputLayersTopologyTestCase)testCase).FirstInputFeatureLayer);
                wkt2 = GetWktFromFeatureLayer(((TwoInputLayersTopologyTestCase)testCase).SecondInputFeatureLayer);
            }
            else
            {
                throw new Exception("TestCase not supported.");
            }
        }
        private void WktImporter_Load(object sender, EventArgs e)
        {
            features = new Collection<Collection<Feature>>();
            if (isTwoInput)
            {
                listBox1.Items.Add("First Layer");
                listBox1.Items.Add("Second Layer");
                secondLayerWktTextBox.Text = wkt2;
            }
            else
            {
                listBox1.Items.Add("Input Layer");
            }
            tbWkt.Text = wkt1;
            listBox1.SelectedIndex = 0;
            fromWktRadio.Checked = true;
            secondFromWktRadio.Checked = true;
        }
        private string GetWktFromFeatureLayer(InMemoryFeatureLayer inMemoryFeatureLayer)
        {
            StringBuilder sb = new StringBuilder();
            string result = string.Empty;
            if (inMemoryFeatureLayer.InternalFeatures.Count > 0)
            {
                foreach (Feature feature in inMemoryFeatureLayer.InternalFeatures)
                {
                    sb.AppendLine(feature.GetWellKnownText() + ";");
                }
                result = sb.ToString();
                result = result.Remove(result.LastIndexOf(";"));
            }
            return result;
        }
        private void btnOK_Click(object sender, EventArgs e)
        {
            if (fromWktRadio.Checked)
            {
                wkt1 = tbWkt.Text;
                features.Add(GetFeaturesFromWkt(wkt1));
            }
            else
            {
                try
                {
                    ShapeFileFeatureLayer layer = new ShapeFileFeatureLayer(shapeFilePathTextBox.Text, ShapeFileReadWriteMode.ReadOnly);
                    layer.Open();
                    features.Add(layer.QueryTools.GetAllFeatures(ReturningColumnsType.NoColumns));
                    layer.Close();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    this.DialogResult = DialogResult.Cancel;
                    this.Close();
                    return;
                }
            }
            if (secondFromWktRadio.Checked)
            {
                wkt2 = secondLayerWktTextBox.Text;
                features.Add(GetFeaturesFromWkt(wkt2));
            }
            else
            {
                try
                {
                    ShapeFileFeatureLayer layer = new ShapeFileFeatureLayer(secondLayerShapeFileTextBox.Text, ShapeFileReadWriteMode.ReadOnly);
                    layer.Open();
                    features.Add(layer.QueryTools.GetAllFeatures(ReturningColumnsType.NoColumns));
                    layer.Close();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    this.DialogResult = DialogResult.Cancel;
                    this.Close();
                    return;
                }
            }
            this.DialogResult = DialogResult.OK;
            this.Close();
        }
        private Collection<Feature> GetFeaturesFromWkt(string wkt)
        {
            Collection<Feature> results = new Collection<Feature>();
            string[] xmls = wkt.Split(';');
            for (int i = 0; i < xmls.Length; i++)
            {
                if (xmls[i] != "")
                {
                    results.Add(new Feature(xmls[i]));
                }
            }
            return results;
        }
        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
            this.Close();
        }
        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listBox1.SelectedIndex == 1)
            {
                firstGroupBox.Enabled = false;
                firstGroupBox.Visible = false;
                secondGroupBox.Visible = true;
                secondGroupBox.Enabled = true;
            }
            else
            {
                firstGroupBox.Enabled = true;
                firstGroupBox.Visible = true;
                secondGroupBox.Visible = false;
                secondGroupBox.Enabled = false;
            }
        }
        private void fromWktRadio_CheckedChanged(object sender, EventArgs e)
        {
            if (fromWktRadio.Checked)
            {
                SetControlEnabledStatus(false, shapeFilePathTextBox, browseButton);
                SetControlEnabledStatus(true, tbWkt);
            }
            else
            {
                SetControlEnabledStatus(true, shapeFilePathTextBox, browseButton);
                SetControlEnabledStatus(false, tbWkt);
            }
        }
        private void SetControlEnabledStatus(bool enabled, params Control[] controls)
        {
            foreach (var item in controls)
            {
                item.Enabled = enabled;
            }
        }
        private void browseButton_Click(object sender, EventArgs e)
        {
            OpenFileDialog open = new OpenFileDialog();
            open.RestoreDirectory = true;
            open.Filter = "Shape Files (*.shp) | *.shp";
            open.Multiselect = false;
            if (open.ShowDialog() == DialogResult.OK)
            {
                shapeFilePathTextBox.Text = open.FileName;
            }
        }
        private void secondBrowseButton_Click(object sender, EventArgs e)
        {
            OpenFileDialog open = new OpenFileDialog();
            open.RestoreDirectory = true;
            open.Filter = "Shape Files (*.shp) | *.shp";
            open.Multiselect = false;
            if (open.ShowDialog() == DialogResult.OK)
            {
                secondLayerShapeFileTextBox.Text = open.FileName;
            }
        }
        private void secondFromWktRadio_CheckedChanged(object sender, EventArgs e)
        {
            if (secondFromWktRadio.Checked)
            {
                SetControlEnabledStatus(false, secondLayerShapeFileTextBox, secondBrowseButton);
                SetControlEnabledStatus(true, secondLayerWktTextBox);
            }
            else
            {
                SetControlEnabledStatus(true, secondLayerShapeFileTextBox, secondBrowseButton);
                SetControlEnabledStatus(false, secondLayerWktTextBox);
            }
        }
    }
}

TopologyTestCase.cs

using System.Collections.ObjectModel;
using System.Text;
using System.Xml;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.DesktopEdition;
namespace TopologyValidation
{
    public abstract class TopologyTestCase
    {
        private string id;
        private string name;
        private string description;
        private bool loadingFromShapeFile;
        private InMemoryFeatureLayer outputFeatureLayer;
        private Collection<InMemoryFeatureLayer> layers;
        private TestCaseInputType testCaseInputType = TestCaseInputType.Default;
        protected TopologyTestCase()
            : this("TopologyTestCase")
        { }
        protected TopologyTestCase(string name)
        {
            this.name = name;
            outputFeatureLayer = new InMemoryFeatureLayer();
            outputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(new GeoColor(180, GeoColor.StandardColors.Red), GeoColor.StandardColors.Black);
            outputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(new GeoColor(180, GeoColor.StandardColors.Red), 2, true);
            outputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(new GeoColor(180, GeoColor.StandardColors.Red), 12);
            outputFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            layers = new Collection<InMemoryFeatureLayer>();
            layers.Add(OutputFeatureLayer);
        }
        public TestCaseInputType TestCaseInputType
        {
            get { return testCaseInputType; }
            set { testCaseInputType = value; }
        }
        public string Id
        {
            get
            {
                return id;
            }
            set
            {
                id = value;
            }
        }
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }
        public string Description
        {
            get
            {
                return description;
            }
            set
            {
                description = value;
            }
        }
        public InMemoryFeatureLayer OutputFeatureLayer
        {
            get
            {
                return outputFeatureLayer;
            }
            protected set
            {
                outputFeatureLayer = value;
            }
        }
 
        public Collection<InMemoryFeatureLayer> Layers
        {
            get
            {
                return layers;
            }
            protected set
            {
                layers = value;
            }
        }
        public bool LoadingFromShapeFile
        {
            get
            {
                return loadingFromShapeFile;
            }
            set
            {
                loadingFromShapeFile = value;
            }
        }
        public void GenerateTestResult()
        {
            GenerateTestResultCore();
        }
        protected abstract void GenerateTestResultCore();
        public TopologyTestCase Clone()
        {
            return CloneCore();
        }
        protected abstract TopologyTestCase CloneCore();
        public void AddInputShape(BaseShape shape)
        {
            AddInputShapeCore(shape);
        }
        protected abstract void AddInputShapeCore(BaseShape shape);
        public void FromXml(XmlNode node)
        {
            FromXmlCore(node);
        }
        protected abstract void FromXmlCore(XmlNode node);
        public void ToXml(string path)
        {
            ToXmlCore(path);
        }
        protected abstract void ToXmlCore(string path);
        public void Clear()
        {
            ClearCore();
        }
        protected virtual void ClearCore()
        {
            loadingFromShapeFile = false;
            OutputFeatureLayer.InternalFeatures.Clear();
        }
        public RectangleShape GetBoundingBox()
        {
            return GetBoundingBoxCore();
        }
        protected abstract RectangleShape GetBoundingBoxCore();
        public TopologyTestCase GenerateTestCaseWithinExtent(RectangleShape extent)
        {
            return GenerateTestCaseWithinExtentCore(extent);
        }
        protected abstract TopologyTestCase GenerateTestCaseWithinExtentCore(RectangleShape extent);
        public void Draw(WinformsMap winformsMap)
        {
            DrawCore(winformsMap);
        }
        protected abstract void DrawCore(WinformsMap winformsMap);
        public virtual string GetOutputInString()
        {
            StringBuilder sb = new StringBuilder();
            string result = string.Empty;
            if (OutputFeatureLayer.InternalFeatures.Count > 0)
            {
                foreach (Feature feature in OutputFeatureLayer.InternalFeatures)
                {
                    sb.AppendLine(feature.GetWellKnownText() + ";");
                }
                result = sb.ToString();
                result = result.Remove(result.LastIndexOf(";"));
            }
            return result;
        }
    }
}

TwoInputLayersTopologyTestCase.cs

using System;
using System.Collections.ObjectModel;
using System.Xml;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.DesktopEdition;
using System.IO;
namespace TopologyValidation
{
    public abstract class TwoInputLayersTopologyTestCase : TopologyTestCase
    {
        private InMemoryFeatureLayer firstInputFeatureLayer;
        private InMemoryFeatureLayer secondInputFeatureLayer;
        private string firstShapeFilePathName;
        private string secondShapeFilePathName;
        private InputFeatureLayerType inputFeatureLayerType;
        public InputFeatureLayerType InputFeatureLayerType
        {
            get { return inputFeatureLayerType; }
            set { inputFeatureLayerType = value; }
        }
        public InMemoryFeatureLayer FirstInputFeatureLayer
        {
            get { return firstInputFeatureLayer; }
        }
        public InMemoryFeatureLayer SecondInputFeatureLayer
        {
            get { return secondInputFeatureLayer; }
        }
        public string FirstShapeFilePathName
        {
            get { return firstShapeFilePathName; }
            set { firstShapeFilePathName = value; }
        }
        public string SecondShapeFilePathName
        {
            get { return secondShapeFilePathName; }
            set { secondShapeFilePathName = value; }
        }
        protected TwoInputLayersTopologyTestCase()
            : this("TwoInputLayersTopologyTestCase")
        { }
        protected TwoInputLayersTopologyTestCase(string name)
            : base(name)
        {
            firstInputFeatureLayer = new InMemoryFeatureLayer();
            secondInputFeatureLayer = new InMemoryFeatureLayer();
            firstInputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(102, 0, 0, 255), GeoColor.FromArgb(255, 0, 0, 255), 2);
            firstInputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.FromArgb(102, 0, 0, 255), 2, true);
            firstInputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.FromArgb(102, 0, 0, 255), 12);
            firstInputFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            secondInputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(102, 0, 255, 0), GeoColor.FromArgb(255, 0, 255, 0), 2);
            secondInputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.FromArgb(102, 0, 255, 0), 2, true);
            secondInputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.FromArgb(102, 0, 255, 0), 12);
            secondInputFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            Layers = new Collection<InMemoryFeatureLayer>();
            Layers.Add(firstInputFeatureLayer);
            Layers.Add(secondInputFeatureLayer);
            Layers.Add(OutputFeatureLayer);
        }
 
        protected override void AddInputShapeCore(BaseShape shape)
        {
            if (InputFeatureLayerType == InputFeatureLayerType.First)
            {
                FirstInputFeatureLayer.InternalFeatures.Add(shape.GetFeature());
            }
            else if (InputFeatureLayerType == InputFeatureLayerType.Second)
            {
                SecondInputFeatureLayer.InternalFeatures.Add(shape.GetFeature());
            }
            else
            {
                throw new Exception("The InputType is wrong");
            }
        }
        protected override RectangleShape GetBoundingBoxCore()
        {
            RectangleShape boundingBox = null;
            if (!LoadingFromShapeFile)
            {
                if (firstInputFeatureLayer.InternalFeatures.Count > 0)
                {
                    firstInputFeatureLayer.Open();
                    boundingBox = firstInputFeatureLayer.GetBoundingBox();
                }
                if (secondInputFeatureLayer.InternalFeatures.Count > 0)
                {
                    secondInputFeatureLayer.Open();
                    if (boundingBox != null)
                    {
                        boundingBox.ExpandToInclude(secondInputFeatureLayer.GetBoundingBox());
                    }
                    else
                    {
                        boundingBox = secondInputFeatureLayer.GetBoundingBox();
                    }
                }
            }
            else
            {
                if (!string.IsNullOrEmpty(firstShapeFilePathName))
                {
                    ShapeFileFeatureLayer coveredShapeFileFeatureLayer = new ShapeFileFeatureLayer(firstShapeFilePathName);
                    coveredShapeFileFeatureLayer.Open();
                    boundingBox = coveredShapeFileFeatureLayer.GetBoundingBox();
                    coveredShapeFileFeatureLayer.Close();
                }
                if (!string.IsNullOrEmpty(secondShapeFilePathName))
                {
                    ShapeFileFeatureLayer coveringShapeFileFeatureLayer = new ShapeFileFeatureLayer(secondShapeFilePathName);
                    coveringShapeFileFeatureLayer.Open();
                    if (boundingBox == null)
                    {
                        boundingBox = coveringShapeFileFeatureLayer.GetBoundingBox();
                    }
                    else
                    {
                        boundingBox.ExpandToInclude(coveringShapeFileFeatureLayer.GetBoundingBox());
                    }
                    coveringShapeFileFeatureLayer.Close();
                }
            }
            return boundingBox;
        }
        protected override TopologyTestCase CloneCore()
        {
            TwoInputLayersTopologyTestCase newObject = (TwoInputLayersTopologyTestCase)Activator.CreateInstance(GetType());
            for (int i = 0; i < Layers.Count; i++)
            {
                for (int j = 0; j < Layers[i].InternalFeatures.Count; j++)
                {
                    newObject.Layers[i].InternalFeatures.Add(Layers[i].InternalFeatures[j]);
                }
            }
            return newObject;
        }
        protected override void ClearCore()
        {
            base.ClearCore();
            firstInputFeatureLayer.InternalFeatures.Clear();
            secondInputFeatureLayer.InternalFeatures.Clear();
        }
        protected override TopologyTestCase GenerateTestCaseWithinExtentCore(RectangleShape extent)
        {
            OutputFeatureLayer.Open();
            firstInputFeatureLayer.Open();
            secondInputFeatureLayer.Open();
            Collection<Feature> outputFeatures = OutputFeatureLayer.QueryTools.GetFeaturesInsideBoundingBox(extent, ReturningColumnsType.NoColumns);
            Collection<Feature> inputPointFeatures = null;
            Collection<Feature> inputPolygonFeatures = null;
            if (!LoadingFromShapeFile)
            {
                inputPointFeatures = firstInputFeatureLayer.QueryTools.GetFeaturesInsideBoundingBox(extent, ReturningColumnsType.NoColumns);
                inputPolygonFeatures = secondInputFeatureLayer.QueryTools.GetFeaturesInsideBoundingBox(extent, ReturningColumnsType.NoColumns);
            }
            else
            {
                ShapeFileFeatureLayer pointShapeFileFeatureLayer = new ShapeFileFeatureLayer(firstShapeFilePathName);
                pointShapeFileFeatureLayer.Open();
                inputPointFeatures = pointShapeFileFeatureLayer.QueryTools.GetFeaturesInsideBoundingBox(extent, ReturningColumnsType.NoColumns);
                ShapeFileFeatureLayer polygonShapeFileFeatureLayer = new ShapeFileFeatureLayer(secondShapeFilePathName);
                polygonShapeFileFeatureLayer.Open();
                inputPointFeatures = polygonShapeFileFeatureLayer.QueryTools.GetFeaturesInsideBoundingBox(extent, ReturningColumnsType.NoColumns);
            }
            TwoInputLayersTopologyTestCase topologyTestCase = (TwoInputLayersTopologyTestCase)Activator.CreateInstance(GetType());
            foreach (Feature feature in outputFeatures)
            {
                topologyTestCase.OutputFeatureLayer.InternalFeatures.Add(feature);
            }
            foreach (Feature feature in inputPointFeatures)
            {
                topologyTestCase.FirstInputFeatureLayer.InternalFeatures.Add(feature);
            }
            foreach (Feature feature in inputPolygonFeatures)
            {
                topologyTestCase.SecondInputFeatureLayer.InternalFeatures.Add(feature);
            }
            return topologyTestCase;
        }
        protected override void FromXmlCore(XmlNode node)
        {
            XmlNode nodeTypeName = node.SelectSingleNode("./TypeName");
            Collection<Feature> outputFeatures = new Collection<Feature>();
            Collection<Feature> inputPointFeatures = new Collection<Feature>();
            Collection<Feature> inputPolygonFeatures = new Collection<Feature>();
            XmlNode nodeID = node.SelectSingleNode("./ID");
            XmlNode nodeName = node.SelectSingleNode("./Name");
            XmlNode nodeDescription = node.SelectSingleNode("./Description");
            XmlNode nodeInput = node.SelectSingleNode("./Input");
            XmlNodeList nodesWKT;
            XmlNode nodePointShapes = nodeInput.SelectSingleNode("./FirstInputShapes");
            if (nodePointShapes != null)
            {
                nodesWKT = nodePointShapes.SelectNodes("./WKT");
                foreach (XmlNode nodeShape in nodesWKT)
                {
                    string wkt = nodeShape.InnerText;
                    inputPointFeatures.Add(new Feature(wkt));
                }
            }
            XmlNode nodePolygonShapes = nodeInput.SelectSingleNode("./SecondInputShapes");
            if (nodePolygonShapes != null)
            {
                nodesWKT = nodePolygonShapes.SelectNodes("./WKT");
                foreach (XmlNode nodeShape in nodesWKT)
                {
                    string wkt = nodeShape.InnerText;
                    inputPolygonFeatures.Add(new Feature(wkt));
                }
            }
            XmlNode nodeOutput = node.SelectSingleNode("./Output");
            nodesWKT = nodeOutput.SelectNodes("./WKT");
            foreach (XmlNode nodeShape in nodesWKT)
            {
                string wkt = nodeShape.InnerText;
                outputFeatures.Add(new Feature(wkt));
            }
            this.Name = nodeName.InnerText;
            this.Description = nodeDescription.InnerText;
            this.Id = nodeID.InnerText;
            foreach (Feature feature in inputPointFeatures)
            {
                this.FirstInputFeatureLayer.InternalFeatures.Add(feature);
            }
            foreach (Feature feature in inputPolygonFeatures)
            {
                this.SecondInputFeatureLayer.InternalFeatures.Add(feature);
            }
            foreach (Feature feature in outputFeatures)
            {
                this.OutputFeatureLayer.InternalFeatures.Add(feature);
            }
        }
        protected override void ToXmlCore(string path)
        {
            XmlDocument doc = new XmlDocument();
            int count = 1;
            string tempPath = path + ".xml";
            while (File.Exists(tempPath))
            {
                tempPath = path + "_" + count + ".xml";
                count++;
            }
            XmlElement caseNode = doc.CreateElement("Case");
            doc.AppendChild(caseNode);
            XmlElement typeNameNode = doc.CreateElement("TypeName");
            typeNameNode.InnerText = GetType().ToString();
            caseNode.AppendChild(typeNameNode);
            XmlElement idNode = doc.CreateElement("ID");
            idNode.InnerText = Guid.NewGuid().ToString();
            caseNode.AppendChild(idNode);
            XmlElement nameNode = doc.CreateElement("Name");
            nameNode.InnerText = Name + (count > 1 ? "_" + (count - 1) : ""); ;
            caseNode.AppendChild(nameNode);
            XmlElement desNode = doc.CreateElement("Description");
            desNode.InnerText = Description;
            caseNode.AppendChild(desNode);
            XmlElement inNode = doc.CreateElement("Input");
            caseNode.AppendChild(inNode);
            XmlElement inCoveredNode = doc.CreateElement("FirstInputShapes");
            inNode.AppendChild(inCoveredNode);
            foreach (var feature in FirstInputFeatureLayer.InternalFeatures)
            {
                XmlElement wktNode = doc.CreateElement("WKT");
                wktNode.InnerText = feature.GetWellKnownText();
                inCoveredNode.AppendChild(wktNode);
            }
            XmlElement inCoverringNode = doc.CreateElement("SecondInputShapes");
            inNode.AppendChild(inCoverringNode);
            foreach (var feature in SecondInputFeatureLayer.InternalFeatures)
            {
                XmlElement wktNode = doc.CreateElement("WKT");
                wktNode.InnerText = feature.GetWellKnownText();
                inCoverringNode.AppendChild(wktNode);
            }
            XmlElement outNode = doc.CreateElement("Output");
            caseNode.AppendChild(outNode);
            foreach (var feature in OutputFeatureLayer.InternalFeatures)
            {
                XmlElement wktNode = doc.CreateElement("WKT");
                wktNode.InnerText = feature.GetWellKnownText();
                outNode.AppendChild(wktNode);
            }
            doc.Save(tempPath);
        }
        protected override void DrawCore(WinformsMap winformsMap)
        {
            LayerOverlay layerOverlay = new LayerOverlay();
            if (!LoadingFromShapeFile)
            {
                foreach (var item in Layers)
                {
                    layerOverlay.Layers.Add(item);
                }
            }
            else
            {
                if (!String.IsNullOrEmpty(firstShapeFilePathName))
                {
                    ShapeFileFeatureLayer.BuildIndexFile(firstShapeFilePathName, BuildIndexMode.DoNotRebuild);
                    ShapeFileFeatureLayer firstInputShapeFileFeatureLayer = new ShapeFileFeatureLayer(firstShapeFilePathName);
                    firstInputShapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(102, 0, 255, 0), GeoColor.FromArgb(255, 0, 255, 0), 2);
                    firstInputShapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.FromArgb(102, 0, 255, 0), 2, true);
                    firstInputShapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.FromArgb(102, 0, 255, 0), 12);
                    firstInputShapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
                    layerOverlay.Layers.Add(firstInputShapeFileFeatureLayer);
                }
                if (!String.IsNullOrEmpty(secondShapeFilePathName))
                {
                    ShapeFileFeatureLayer.BuildIndexFile(secondShapeFilePathName, BuildIndexMode.DoNotRebuild);
                    ShapeFileFeatureLayer secondInputShapeFileFeatureLayer = new ShapeFileFeatureLayer(secondShapeFilePathName);
                    secondInputShapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(102, 0, 0, 255), GeoColor.FromArgb(255, 0, 0, 255), 2);
                    secondInputShapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.FromArgb(102, 0, 0, 255), 2, true);
                    secondInputShapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.FromArgb(102, 0, 0, 255), 12);
                    secondInputShapeFileFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
                    layerOverlay.Layers.Add(secondInputShapeFileFeatureLayer);
                }
                layerOverlay.Layers.Add(OutputFeatureLayer);
            }
            winformsMap.Overlays.Clear();
            winformsMap.Overlays.Add(layerOverlay);
            winformsMap.Refresh();
        }
    }
}

PointsMustBeCoveredByBoundaryOfPolygonsTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class PointsMustBeCoveredByBoundaryOfPolygonsTopologyTestCase : PointAndPolygonInputLayersTopologyTestCase
    {
        public PointsMustBeCoveredByBoundaryOfPolygonsTopologyTestCase()
            : this("PointsMustBeCoveredByBoundaryOfPolygonsTopologyTestCase")
        { }
        public PointsMustBeCoveredByBoundaryOfPolygonsTopologyTestCase(string name)
            : base(name)
        { }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.PointsMustBeCoveredByBoundaryOfPolygons(FirstInputFeatureLayer.InternalFeatures, SecondInputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

PointsMustBeCoveredByEndPointOfLinesTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class PointsMustBeCoveredByEndPointOfLinesTopologyTestCase : PointAndLineInputLayersTopologyTestCase
    {
        public PointsMustBeCoveredByEndPointOfLinesTopologyTestCase()
            : this("PointsMustBeCoveredByEndPointOfLinesTopologyTestCase")
        { }
        public PointsMustBeCoveredByEndPointOfLinesTopologyTestCase(string name)
            : base(name)
        { }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.PointsMustBeCoveredByEndPointOfLines(FirstInputFeatureLayer.InternalFeatures, SecondInputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

PointsMustBeCoveredByLinesTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class PointsMustBeCoveredByLinesTopologyTestCase : PointAndLineInputLayersTopologyTestCase
    {
        public PointsMustBeCoveredByLinesTopologyTestCase()
            : this("PointsMustBeCoveredByLinesTopologyTestCase")
        { }
        public PointsMustBeCoveredByLinesTopologyTestCase(string name)
            : base(name)
        { }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.PointsMustBeCoveredByLines(FirstInputFeatureLayer.InternalFeatures, SecondInputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

PointsMustBeProperlyInsidePolygonsTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class PointsMustBeProperlyInsidePolygonsTopologyTestCase : PointAndPolygonInputLayersTopologyTestCase
    {
        public PointsMustBeProperlyInsidePolygonsTopologyTestCase()
            : this("PointsMustBeProperlyInsidePolygonsTopologyTestCase")
        { }
        public PointsMustBeProperlyInsidePolygonsTopologyTestCase(string name)
            : base(name)
        { }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.PointsMustBeProperlyInsidePolygons(FirstInputFeatureLayer.InternalFeatures, SecondInputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

PolygonsBoundaryMustBeCoveredByBoundaryOfPolygonsTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class PolygonsBoundaryMustBeCoveredByBoundaryOfPolygonsTopologyTestCase : TwoInputLayersTopologyTestCase
    {
        public PolygonsBoundaryMustBeCoveredByBoundaryOfPolygonsTopologyTestCase()
            : this("PolygonsBoundaryMustBeCoveredByBoundaryOfPolygonsTopologyTestCase")
        { }
        public PolygonsBoundaryMustBeCoveredByBoundaryOfPolygonsTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.PolygonAndPolygon;
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.PolygonsBoundaryMustBeCoveredByBoundaryOfPolygons(FirstInputFeatureLayer.InternalFeatures, SecondInputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

PolygonsBoundaryMustBeCoveredByLinesTopologyTestCase.cs

using System;
using System.Collections.Generic;
using System.Text;
using ThinkGeo.MapSuite.Core;
using System.Collections.ObjectModel;
namespace TopologyValidation
{
    public class PolygonsBoundaryMustBeCoveredByLinesTopologyTestCase : LineAndPolygonInputLayersTopologyTestCase
    {
        public PolygonsBoundaryMustBeCoveredByLinesTopologyTestCase()
            : this("PolygonsBoundaryMustBeCoveredByLinesTopologyTestCase")
        { }
        public PolygonsBoundaryMustBeCoveredByLinesTopologyTestCase(string name)
            : base(name)
        { }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.PolygonsBoundaryMustBeCoveredByLines(SecondInputFeatureLayer.InternalFeatures, FirstInputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

PolygonsMustBeCoveredByFeatureClassOfPolygonsTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class PolygonsMustBeCoveredByFeatureClassOfPolygonsTopologyTestCase : TwoInputLayersTopologyTestCase
    {
        public PolygonsMustBeCoveredByFeatureClassOfPolygonsTopologyTestCase()
            : this("PolygonsMustBeCoveredByFeatureClassOfPolygonsTopologyTestCase")
        { }
        public PolygonsMustBeCoveredByFeatureClassOfPolygonsTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.PolygonAndPolygon;
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.PolygonsMustBeCoveredByFeatureClassOfPolygons(FirstInputFeatureLayer.InternalFeatures, SecondInputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (Feature shape in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(shape);
            }
        }
    }
}

PolygonsMustBeCoveredByPolygonsTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class PolygonsMustBeCoveredByPolygonsTopologyTestCase : TwoInputLayersTopologyTestCase
    {
        public PolygonsMustBeCoveredByPolygonsTopologyTestCase()
            : this("PolygonsMustBeCoveredByPolygonsTopologyTestCase")
        { }
        public PolygonsMustBeCoveredByPolygonsTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.PolygonAndPolygon;
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.PolygonsMustBeCoveredByPolygons(FirstInputFeatureLayer.InternalFeatures, SecondInputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (Feature shape in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(shape);
            }
        }
    }
}

PolygonsMustBeLargerThanClusterToleranceTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class PolygonsMustBeLargerThanClusterToleranceTopologyTestCase : OneInputLayerTopologyTestCase
    {
        private double tolerance = 30;
        private InMemoryFeatureLayer assistantLayer;
        public PolygonsMustBeLargerThanClusterToleranceTopologyTestCase()
            : this("PolygonsMustBeLargerThanClusterToleranceTopologyTestCase")
        { }
        public PolygonsMustBeLargerThanClusterToleranceTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TopologyValidation.TestCaseInputType.Polygon;
            InputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.FromArgb(70, 0, 0, 255), 2, true);
            InputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(20, 0, 0, 255), GeoColor.FromArgb(255, 0, 0, 255), 2);
            OutputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.FromArgb(200, GeoColor.StandardColors.Green), 2, true);
            OutputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(102, 0, 0, 255), GeoColor.FromArgb(255, 0, 0, 255), 2);
            OutputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.SimpleColors.Transparent, 10);
            assistantLayer = new InMemoryFeatureLayer();
            assistantLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(20, 255, 255, 255), GeoColor.FromArgb(70, 0, 0, 0));
            assistantLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimplePointStyle(PointSymbolType.Circle, GeoColor.SimpleColors.Red, 5);
            assistantLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            this.Layers.Add(assistantLayer);
        }
        public double Tolerance
        {
            get { return tolerance; }
            set { tolerance = value; }
        }
        public InMemoryFeatureLayer AssistantLayer
        {
            get { return assistantLayer; }
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.PolygonsMustBeLargerThanClusterTolerance(InputFeatureLayer.InternalFeatures, Tolerance);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            assistantLayer.InternalFeatures.Clear();
            foreach (Feature polygonShape in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(polygonShape);
                foreach (Vertex vertex in ((PolygonShape)polygonShape.GetShape()).OuterRing.Vertices)
                {
                    EllipseShape ellipseShape = new EllipseShape(new PointShape(vertex), Tolerance);
                    AssistantLayer.InternalFeatures.Add(new Feature(ellipseShape));
                    Feature pointFeature = new Feature(vertex);
                    AssistantLayer.InternalFeatures.Add(pointFeature);
                }
                foreach (var ring in ((PolygonShape)polygonShape.GetShape()).InnerRings)
                {
                    foreach (var vertex in ring.Vertices)
                    {
                        EllipseShape ellipseShape = new EllipseShape(new PointShape(vertex), Tolerance);
                        AssistantLayer.InternalFeatures.Add(new Feature(ellipseShape));
                        Feature pointFeature = new Feature(vertex);
                        AssistantLayer.InternalFeatures.Add(pointFeature);
                    }
                }
            }
        }
        protected override void ClearCore()
        {
            base.ClearCore();
            assistantLayer.InternalFeatures.Clear();
        }
    }
}

PolygonsMustContainPointTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class PolygonsMustContainPointTopologyTestCase : PointAndPolygonInputLayersTopologyTestCase
    {
        public PolygonsMustContainPointTopologyTestCase()
            : this("PolygonsMustContainPointTopologyTestCase")
        { }
        public PolygonsMustContainPointTopologyTestCase(string name)
            : base(name)
        { }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.PolygonsMustContainPoint(SecondInputFeatureLayer.InternalFeatures, FirstInputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (Feature shape in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(shape);
            }
        }
    }
}

PolygonsMustCoverEachOtherTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class PolygonsMustCoverEachOtherTopologyTestCase : TwoInputLayersTopologyTestCase
    {
        public PolygonsMustCoverEachOtherTopologyTestCase()
            : this("PolygonsMustCoverEachOtherTopologyTestCase")
        { }
        public PolygonsMustCoverEachOtherTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.PolygonAndPolygon;
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.PolygonsMustCoverEachOther(FirstInputFeatureLayer.InternalFeatures, SecondInputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

PolygonsMustNotHaveGapsTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class PolygonsMustNotHaveGapsTopologyTestCase : OneInputLayerTopologyTestCase
    {
        public PolygonsMustNotHaveGapsTopologyTestCase()
            : this("PolygonsMustNotHaveGapsTopologyTestCase")
        { }
        public PolygonsMustNotHaveGapsTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.Polygon;
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.PolygonsMustNotHaveGaps(InputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (Feature shape in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(shape);
            }
        }
    }
}

PolygonsMustNotOverlapTopologyTestCase.cs

using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class PolygonsMustNotOverlapTopologyTestCase : OneInputLayerTopologyTestCase
    {
        public PolygonsMustNotOverlapTopologyTestCase()
            : this("PolygonsMustNotOverlapTopologyTestCase")
        { }
        public PolygonsMustNotOverlapTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.Polygon;
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.PolygonsMustNotOverlap(InputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (Feature item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

PolygonsMustNotOverlapWithPolygonsTopologyTestCase.cs

using ThinkGeo.MapSuite.Core;
using System.Collections.ObjectModel;
namespace TopologyValidation
{
    public class PolygonsMustNotOverlapWithPolygonsTopologyTestCase : TwoInputLayersTopologyTestCase
    {
        public PolygonsMustNotOverlapWithPolygonsTopologyTestCase()
            : this("PolygonsMustNotOverlapWithPolygonsTopologyTestCase")
        { }
        public PolygonsMustNotOverlapWithPolygonsTopologyTestCase(string name)
            : base(name)
        {
            TestCaseInputType = TestCaseInputType.PolygonAndPolygon;
        }
        protected override void GenerateTestResultCore()
        {
            Collection<Feature> results = null;
            if (!LoadingFromShapeFile)
            {
                results = TopologyValidator.PolygonsMustNotOverlapWithPolygons(FirstInputFeatureLayer.InternalFeatures, SecondInputFeatureLayer.InternalFeatures);
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (var item in results)
            {
                OutputFeatureLayer.InternalFeatures.Add(item);
            }
        }
    }
}

TestCaseInputType.cs

namespace TopologyValidation
{
    public enum TestCaseInputType
    {
        Default,
        Point,
        Line,
        Polygon,
        PointAndLine,
        PointAndPolygon,
        LineAndLine,
        LineAndPolygon,
        PolygonAndPolygon,
        PointAndLineAndPolygon
    }
}

ToleranceForm.cs

using System;
using System.Windows.Forms;
namespace TopologyValidation
{
    public partial class ToleranceForm : Form
    {
        private double tolerance;
        public double Tolerance
        {
            get { return tolerance; }
            set { tolerance = value; }
        }
        public ToleranceForm()
        {
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            tolerance = double.Parse(textBox1.Text);
            this.DialogResult = DialogResult.OK;
        }
    }
}

ValidateShapesTopologyTestCase.cs

using System.Collections.ObjectModel;
using System.Text;
using System.Xml;
using ThinkGeo.MapSuite.Core;
namespace TopologyValidation
{
    public class ValidateShapesTopologyTestCase : OneInputLayerTopologyTestCase
    {
        private Collection<InvalidFeatureInfo> invalidShapeInfos;
        public ValidateShapesTopologyTestCase()
            : this("ValidateShapesTopologyTestCase")
        { }
        public ValidateShapesTopologyTestCase(string name)
            : base(name)
        {
            invalidShapeInfos = new Collection<InvalidFeatureInfo>();
            OutputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(new GeoColor(180, GeoColor.StandardColors.Green), GeoColor.StandardColors.Black);
            OutputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(new GeoColor(180, GeoColor.StandardColors.Green), 2, true);
            OutputFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(new GeoColor(180, GeoColor.StandardColors.Green), 12);
        }
        public Collection<InvalidFeatureInfo> InvalidShapeInfos
        {
            get { return invalidShapeInfos; }
        }
        protected override void GenerateTestResultCore()
        {
            InvalidShapeInfos.Clear();
            foreach (var item in InputFeatureLayer.InternalFeatures)
            {
                if (item.CanMakeValid && !item.IsValid())
                {
                    InvalidFeatureInfo info = new InvalidFeatureInfo();
                    info.InvalidFeature = item;
                    info.ErrorDescription = item.GetInvalidReason();
                    info.FixedFeature = item.MakeValid();
                    invalidShapeInfos.Add(info);
                }
            }
            OutputFeatureLayer.InternalFeatures.Clear();
            foreach (InvalidFeatureInfo invalidShapeInfo in invalidShapeInfos)
            {
                OutputFeatureLayer.InternalFeatures.Add(invalidShapeInfo.FixedFeature);
            }
        }
        public override string GetOutputInString()
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < invalidShapeInfos.Count; i++)
            {
                sb.AppendLine("Case " + i.ToString());
                sb.AppendLine(InvalidShapeInfos[i].ToString());
            }
            return sb.ToString();
        }
        protected override void FromXmlCore(XmlNode node)
        {
            BaseShape.GeometryLibrary = GeometryLibrary.Managed;
            base.FromXmlCore(node);
            BaseShape.GeometryLibrary = GeometryLibrary.Unmanaged;
        }
    }
}
source_code_desktopeditionsample_topologyvalidation_cs_120904.zip.txt · Last modified: 2015/09/09 03:32 by admin