Select to view content in your preferred language

Get difference between two shapefile

12276
14
08-08-2011 02:48 AM
ValeriaAndronaco
Emerging Contributor
Hi forum,

I use ArcMap 9.3 and I would like to create a toolbar that query two shapefiles and get the difference between them.
I think that I need to perform a SelectByLocation but how do this whith c# or vb.net language?
Can you help me please?

Thanks a lot in advance!
0 Kudos
14 Replies
DubravkoAntonic
Occasional Contributor
Please post some more info.
But if we assume you have polygons in those shape files that are in same projection and you would like ti see differences in geometry between there two features. And in case you know some atribute value that binds two features that you  would like to compare by their geometry.

If all these assumptions are correct you can use ITopologicalOperator.Difference to get difference polygons but you should use it twice once to see difference polygons that are outside and second time to see these that are inside start geometry.
http://resources.esri.com/help/9.3/arcgisengine/arcobjects/esrigeometry/itopologicaloperator_differe...
if you have desktop sdk you will find there descriptive picture of this tool.
0 Kudos
ValeriaAndronaco
Emerging Contributor
Thanks al lot for the answer!
I have two identical shapefiles, with the same fields.
The two shape refer to two different years than these should be have same geometric or alfanumeric difference. I will obtain a new shapefile with these difference.

How can I use ITopologicalOperator.Difference to obtain this result?

Thanks thanks thanks for the help!!!
0 Kudos
DubravkoAntonic
Occasional Contributor
ITopologicalOperator is implemented by all high level geometries .... See SDK link, read, re read, and try to somehow visualize on map geometries results.

Usage of ITopologicalOperator :[INDENT]
ITopologicalOperator2 pTopOp = pFeature.ShapeCopy as ITopologicalOperator2;
IGeometry differenceGeometry = pTopOp.Difference(pSegment);

pTopOp = differenceGeometry as ITopologicalOperator2;
pTopOp.IsKnownSimple_2 = false;
pTopOp.Simplify();

pFeature.Shape = pTopOp as IGeometry;
pFeature.Store();
[/INDENT]
0 Kudos
ValeriaAndronaco
Emerging Contributor
THANKS!!!

I'm trying the following code
IMxDocument itfMxDoc;
            IMap pmap;
            IFeatureCursor itfCursor1;
            IFeatureCursor itfCursor2;
            IFeature itfFeature1;
            IFeature itfFeature2;
            IFeatureLayer pflayer1;
            IFeatureLayer pflayer2;

            itfMxDoc = m_application.Document as IMxDocument;
            pmap = itfMxDoc.FocusMap;

            pflayer1 = GetLayerByName("Shp1");
            IFeatureSelection pFlSelection = pflayer1 as IFeatureSelection;

            // get index from selected feature   
   //but I will not select anything
            IEnumIDs itfListId = pFlSelection.SelectionSet.IDs;
            itfListId.Reset();
            int Index = itfListId.Next();
            itfFeature1 = pflayer1.FeatureClass.GetFeature(Index);

            // get your buffer
            ITopologicalOperator pTopo = itfFeature1.ShapeCopy as ITopologicalOperator;
            IPolygon pPolygon = pTopo.Buffer(1) as IPolygon;

            pflayer2 = GetLayerByName("Shp2");

            ISpatialFilter itfFilter;
            itfFilter = new SpatialFilter();

            itfFilter.Geometry = pPolygon as IGeometry;
            itfFilter.GeometryField = pflayer2.FeatureClass.ShapeFieldName;
            itfFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelEnvelopeIntersects;

            // get your points inside your buffer 
            itfCursor2 = pflayer2.FeatureClass.Search(itfFilter, false);

            itfFeature2 = itfCursor2.NextFeature();

            // Loop for each point in your buffer
            while (itfFeature2 != null)
            {

                // Get feature id from each feature to select later.
                itfFeature2 = itfCursor2.NextFeature();

            }


but I have same problem.
First of all, I will not select anythyng in the shape but I wold like to calculate the difference between the totla fields of the shape.
Can you read/correct my code please?

About your code, what should I pass as "pSegment"?

Thank for your contribute!
Thanks a lot!!!
The name of my shape are Shp1 and Shp2
0 Kudos
DubravkoAntonic
Occasional Contributor
This is how you can select features by some atribute
http://resources.esri.com/help/9.3/arcgisengine/arcobjects/esrigeodatabase/iqueryfilter_example.htm

Did read, but have no time to correct - implement all that. I think you can do it. If not, post again.
More info about querying features are here
http://resources.esri.com/help/9.3/arcgisengine/java/doc/aa43bbb3-6427-11dc-9ca3-0b35f906bb2e.htm

You sad that you will not select anything, but you are trying to browse through section set. It seems to me that you use some copy paste code that you didn't understand. But anyway to get through features from some layer you should use query.

Selecting features that will after that appear in SelectinSet you can do by IFeatureClass.Select see SDK

Use cursor recycling.
To compare fields you should use IFeatures.getField(fieldIndex) for each feature and compare it. You can use base compare method object.equals(feature1FieldAtSameIndex, feature2FieldAtSameIndex); see C# MSDN for Object.Equals(obja, objB);
http://msdn.microsoft.com/en-us/library/w4hkze5k.aspx

this is ok if the fieldcount and field order are same, if not use fieldfind by finding field index by name and creating some array... it can be many solutions but I don't know details

//before loop
int equalFieldCount = 0;

// in the loop
bool equal = Object.Equal(pfeature1.getValue(i), pfeature2.getValue(i))
if(equal)[INDENT] equalFieldCount++;
[/INDENT]// after loop
bool allFieldsAreEqual = false;
if(pfeature.fields.fieldsCount - "numberOfGeometryFields" == equalFieldCount)[INDENT] allFieldsAreEqual = true;
[/INDENT]
pSegment is any geometry object polygon, line, point.
0 Kudos
G__Venkata_VijayaKumar
Occasional Contributor
Hi,

Your requirement is still not clear.
Do i understand that you are trying to identify all the features which have "current values" in "certain fields" in your shape file "which are different from values" compared to another version of "the same shape file" in the past?

Vijay
0 Kudos
ValeriaAndronaco
Emerging Contributor
Hi,

thanks to all forum for your availability and sorry if I continue to disturbe you but I'm in a difficult situation.
I have attached the screenshot of the attribute table of the two shape.
The fields are the same and in the same order.
I have the necessity to compare the two shape to get the geometric and alfanumeric difference.
Later, I have to save the results into a new shape.

I don't know how get all the fields of the two shape and compare it and how to save the final result.

Can you suggest me some code?
Do not think I'm lazy, I'm still doing tests but without results.

I hope that you help me!

Thanks in advance.
0 Kudos
DubravkoAntonic
Occasional Contributor
Try this code, didn't tested in VS but there can be only miss typed something.

//Compare Features
public bool FeaturesEqual(IFeature pFeatureA, IFeature pFeatureB)
{[INDENT] // attribute equal test
int diffCount=0;
for(int i=0; i<pFeatureA.Fields.FieldCount; i++)
{[INDENT] bool equal = Object.Equal(pFeatureA.getValue(i), pFeatureA.getValue(i));
if(!equal){[INDENT] diffCount++;
}
[/INDENT][/INDENT]}

// geometry equal test
IArea pAreaA = pFeatureA.Shape;
IArea pAreaB = pFeatureA.Shape;

if(pAreaA.Area != pAreaB.Area){[INDENT] diffCount++;
}
[/INDENT]if(diffCount >0){[INDENT]  return false;
}
[/INDENT]return true;
[/INDENT]}

IArea
http://resources.esri.com/help/9.3/arcgisengine/arcobjects/esrigeometry/iarea.htm
IFeaure
http://resources.esri.com/help/9.3/ArcGISDesktop/ArcObjects/esrigeodatabase/IFeature.htm

it can be used IRowCompare but i vould rather test it before posting some code
http://resources.esri.com/help/9.3/ArcGISDesktop/ArcObjects/esriGeoDatabase/IRowCompare.htm

from documentation you see that Feature implements IRowCompare  so you can do

// use this in for loop
IRwoCompare pRowComapre   = pFeatureA as IRowCompare;
IRow pRowB = pFeatureB as IRow;

if(pRowCompare.IsEqual)
... do some logic if equal
else
... do some not equal logic

please test this second because I used this long ago and don't have chance to test it now but it rings me that it will be helpful.
0 Kudos
ValeriaAndronaco
Emerging Contributor
Hi Antonic,

I have tried to write code using your suggestion but I can not get any results.
Thisi is the code that I have used to the click event of the command tool:

public override void OnClick()
        {
            IFeatureLayer pflayer1;
            IFeatureLayer pflayer2;
            IFeature featureA;
            IFeature featureB;

            pflayer1 = GetLayerByName("Shape1");
            IFeatureSelection p1FlSelection = pflayer1 as IFeatureSelection;
           int[] idList = GetFidList(@"D:\ShapeFile1").ToArray();
            IFeatureCursor feature1Cursor = pflayer1.FeatureClass.GetFeatures(idList, false);
            featureA = feature1Cursor.NextFeature();

            pflayer2 = GetLayerByName("Shape2");
            int[] oidList = GetFidList(@"D:\ShapeFile1").ToArray();
            IFeatureCursor feature2Cursor = pflayer2.FeatureClass.GetFeatures(oidList, false);
            featureB = feature2Cursor.NextFeature();

            List<int> fidList = new List<int>();
            while (featureA != null)
            {
                while (featureB != null)
                {
                    string risultato = FeaturesEqual(featureA, featureB);
                    if (!String.IsNullOrEmpty(risultato))
                        fidList.Add(Convert.ToInt32(risultato));
                    featureB = feature2Cursor.NextFeature();
                }
                feature2Cursor = pflayer2.FeatureClass.GetFeatures(oidList, false);
                featureB = feature2Cursor.NextFeature();
                feature1Cursor = pflayer1.FeatureClass.GetFeatures(idList, false);
                featureA = feature1Cursor.NextFeature();
            }
//At this point it stops and leaves
            string elenco = String.Empty;
            foreach (int numero in fidList)
            {
                elenco += numero + ",";
            }
            elenco = elenco.Trim(',');

            IMap pMap = m_hookHelper.FocusMap;
            IActiveView pActiveView = (IActiveView)m_hookHelper.FocusMap;
            string where = "FID IN (" + elenco + ")";

            SelectMapFeaturesByAttributeQuery(pActiveView, pflayer1, where);

        }


At the point commented in blue color the procedure stops and leaves.
This is the red function:
//Compare Features
//temporarily I consider only attribute compare and not geometry
        public string FeaturesEqual(IFeature pFeatureA, IFeature pFeatureB)
        {
            // attribute equal test
            int diffCount = 0;
            for (int i = 2; i < pFeatureA.Fields.FieldCount; i++)
            {
                string valore1 = pFeatureA.get_Value(i).ToString();
                string valore2 = pFeatureB.get_Value(i).ToString();
                bool equal = ESRI.ArcGIS.Geodatabase.Object.Equals(pFeatureA.get_Value(i), pFeatureB.get_Value(i));
                if (!equal)
                {
                    diffCount++;
                }
                if (diffCount > 0)
                    return pFeatureA.OID.ToString();

            }
            return String.Empty;

            //// geometry equal test
            //IArea pAreaA = pFeatureA.Shape as IArea;
            //IArea pAreaB = pFeatureB.Shape as IArea;

            //if (pAreaA.Area != pAreaB.Area)
            //{
            //    diffCount++;
            //}

            //if (diffCount > 0)
            //{
            //    return false;
            //}

            //return true;

        }

public static List<int> GetFidList(string path)
        {
            List<int> fidList = new List<int>();

            String shapefileStringTemplate =
    "Provider=ESRI.GeoDB.OleDB.1;Data Source={0};" +
    "Extended Properties=workspacetype=esriDataSourcesFile.ShapefileWorkspaceFactory.1;Geometry={1}";
            String connectionString = String.Format(shapefileStringTemplate, path,
              "Fabbricati");

            OleDbConnection myOleDbConnection = new OleDbConnection(connectionString);
            OleDbCommand command = myOleDbConnection.CreateCommand();

            command.CommandType = CommandType.Text;
            command.CommandText = String.Format(@"SELECT FID FROM FABBRICATI");

            try
            {
                myOleDbConnection.Open();
                OleDbDataReader reader = command.ExecuteReader();

                while (reader.Read() == true)
                {
                    fidList.Add(
                        Convert.IsDBNull(reader["FID"]) ? 0 : Convert.ToInt32(reader["FID"])
                        );
                }

                reader.Close();
                return fidList;

            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                if (myOleDbConnection.State != ConnectionState.Closed)
                    myOleDbConnection.Close();
            }
        }


Can you see the error?
I trust in your help!!!
0 Kudos