Azure / azure-cosmos-dotnet-v2

Contains samples and utilities relating to the Azure Cosmos DB .NET SDK
MIT License
577 stars 837 forks source link

How to calculate Centroid of MultiLineString for Microsoft.Azure.Documents.Spatial? #764

Open ranouf opened 4 years ago

ranouf commented 4 years ago

Hi,

I use Microsoft.Azure.DocumentDB.Core, Version=2.5.1.0, I have a Geometry Type as MultiLineString. I would like to calculate the centroid. I got the data from a GeoJson that I load in memory before putting in CosmosDb. To increase the getting of data, the center is already calculated before putting the Data in CosmosDB. From what I see here Centroid functionality is available for System.Data.Spatial: => https://docs.microsoft.com/en-us/ef/core/modeling/spatial => https://docs.microsoft.com/en-us/dotnet/api/system.data.spatial.dbgeometry.centroid?view=netframework-4.8

But not for Microsoft.Azure.Documents.Spatial? Do you plan to add it soon? Did I miss something? Is there a way to convert MultineLineString from Microsoft.Azure.Documents.Spatial to system.data.spatial.dbgeometry to get the centroid, then convert the centroid to Microsoft.Azure.Documents.Spatial? Or is there someone to know how to calculate the centroid by code?

Thanks

ranouf commented 4 years ago

As MultiLineString Type is not accessible, I had to deserialize Geometry object then convert it to Spatial MultiLineString:

    public static Point CalculateCentroid(Geometry geometry) //Microsoft.Azure.Documents.Spatial.Geometry
    {
        if (geometry.Type == GeometryType.MultiLineString)
        {
            var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
            var multiLineString = JToken.FromObject(geometry);
            var lineStrings = multiLineString["coordinates"]
                .ToObject<IList<IList<double[]>>>()
                .Select(e =>
                    geometryFactory.CreateLineString(
                        e.Select(d => new Coordinate(d[0], d[1])).ToArray()
                    )
                )
                .ToArray();

            var centroid = geometryFactory
                .CreateMultiLineString(lineStrings)
                .Centroid;
            return new Point(centroid.X, centroid.Y);

        }
        else
        {
            throw new NotImplementedException($"'{geometry.Type}'!");
        }
    }