A'dan B'ye mesafe B'den A'ya aynıdır ve A'dan A'ya mesafe sıfırdır, bu nedenle yarım matris size biraz iş kazandıracaktır.
IProximityOperator kenardan mesafeyi döndürür. Aşağıdaki kod, her çokgenin sentroidinde ortalanmış bir azimuthal izdüşümü kullanır (çizgilerle de çalışmalıdır). Çokgenler çok karmaşık değilse (veya çok fazla belleğiniz varsa) tüm geometrileri belleğe yüklerseniz, onları yansıtan daha hızlı olur. (Bu ayrıntılı olarak test edilmemiştir).
public class Pair
{
public int Oid1;
public int Oid2;
public double Dist;
public static void TestGetDistances()
{
IWorkspaceFactory wsf = new ESRI.ArcGIS.DataSourcesGDB.FileGDBWorkspaceFactoryClass();
string path = @"C:\Program Files\ArcGIS\DeveloperKit10.0\Samples\data\Usa\USA.gdb";
var fws = wsf.OpenFromFile(path, 0) as IFeatureWorkspace;
IFeatureClass fc = fws.OpenFeatureClass("states");
var halfMatrix = Pair.GetPairs(fc);
}
/// <summary>
/// key is oid of each feature, value is pairs for features with smaller oids.
/// </summary>
/// <param name="fc"></param>
/// <returns></returns>
public static SortedList<int, List<Pair>> GetPairs(IFeatureClass fc)
{
ISpatialReferenceFactory3 srf = new SpatialReferenceEnvironmentClass();
IProjectedCoordinateSystem pcs =
srf.CreateProjectedCoordinateSystem((int)esriSRProjCSType.esriSRProjCS_WGS1984N_PoleAziEqui);
var outList = new SortedList<int, List<Pair>>();
IFeatureCursor fCur = fc.Search(null, true);
IFeature f;
while ((f = fCur.NextFeature()) != null)
{
var pairs = GetDistances(f, pcs);
Debug.Print("{0} has {1} pairs", f.OID, pairs.Count);
outList.Add(f.OID, pairs);
}
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(fCur);
return outList;
}
private static IPoint GetGCSCentroid(IGeometry geom)
{
if (geom.SpatialReference is IProjectedCoordinateSystem)
{
geom.Project(((IProjectedCoordinateSystem)geom.SpatialReference).GeographicCoordinateSystem);
}
IArea a = geom is IArea ? geom as IArea : geom.Envelope as IArea;
return a.Centroid;
}
/// <summary>
/// return a list of all other features whose OID is lesser than f1
/// </summary>
/// <param name="f1"></param>
/// <param name="pcs"></param>
/// <returns></returns>
private static List<Pair> GetDistances(IFeature f1, IProjectedCoordinateSystem pcs)
{
IPoint centroid = GetGCSCentroid(f1.ShapeCopy);
pcs.set_CentralMeridian(true, centroid.X);
((IProjectedCoordinateSystem2)pcs).LatitudeOfOrigin = centroid.Y;
var g1 = f1.ShapeCopy;
g1.Project(pcs);
var outList = new List<Pair>();
var fc = f1.Class as IFeatureClass;
var proxOp = g1 as IProximityOperator;
IFeatureCursor fCur = fc.Search(null, true);
IFeature f2 = null;
while ((f2 = fCur.NextFeature()) != null)
{
if (f2.OID < f1.OID)
{
var g2 = f2.ShapeCopy;
g2.Project(pcs);
outList.Add(new Pair()
{
Oid1 = f1.OID,
Oid2 = f2.OID,
Dist = proxOp.ReturnDistance(g2)
});
}
}
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(fCur);
return outList;
}
}