How to persist geometry across transforms

Editor
Jun 6, 2013 at 11:51 AM
Hi,

I have some objects that I would like to track across a map. The coordinates come through as lat longs. If I create a geometry based on these latlongs and store a reference to that geometry in my object, it is set to null by the coordinate transform. I understand why, because it is effectively a different geometry. But what is the correct pattern for doing this?

How can I have a custom object, that I can update the coordinates (or geom) and this change be persisted through to the rendering on the map?

Do I have to get the geometry from data provider every time I update it rather than storing a reference to the geom in my object?

Thanks,

Rob
Editor
Jun 6, 2013 at 11:53 AM
And how do I set the ID of a geometry? If I use Geometry provider as the datasource. how do I set the id of the geometry so that I can use the GetGeometriesbyId function?

Thanks again
Coordinator
Jun 6, 2013 at 12:46 PM
Edited Jun 6, 2013 at 12:47 PM
Do I have to get the geometry from data provider every time I update it rather than storing a reference to the geom in my object?
Yes, you could use GeometryFeatureProvider or implement your own IProvider that acts as a proxy to your business objects.
Editor
Jun 6, 2013 at 1:01 PM
I'm using this at the moment

Collection<GeoAPI.Geometries.IGeometry> geomColl = new Collection<GeoAPI.Geometries.IGeometry>();
            //Get the default geometry factory

            GeoAPI.GeometryServiceProvider.Instance = new NetTopologySuite.NtsGeometryServices();
            var gf = GeoAPI.GeometryServiceProvider.Instance.CreateGeometryFactory();
            int count = 0;


            foreach (var cam in camList)
            {
                if (count == 10) break;

                cam.GetImage();
               var myPoint = gf.CreatePoint(new Coordinate(cam.lon,cam.lat));
               cam.myGeom = myPoint;

               myPoint.UserData = cam;

               geomColl.Add(myPoint);

               count += 1;

            }

            this.DataSource = new SharpMap.Data.Providers.GeometryProvider(geomColl);

I also noticed that Userdata does not persist if you use a geographic transform either. Probably for the exact same reason.

So how would I set the ID of the geometry so that I could properly reference to it?, or how would I other wise persist my reference to the geometry?

Thanks,

Rob
Coordinator
Jun 6, 2013 at 1:46 PM
Edited Jun 6, 2013 at 1:48 PM
As I said, I'd create a proxy provider. That is really not that difficult and it solves all your problems
public class CamProvider : SharpMap.Data.Providers.BaseProvider
{
    private readonly List<Cam> _camList;

    public IList<Cam> CamList { get { return _camList; } }

    private FeatureDataTable CreateEmptyTable()
    {
        /// Setup a FaetureDataTable that matches your "Cam" object, at least the ID
        var fdt = new FeatureDataTable();
        fdt.Columns.Add("CamId", typeof(uint));
        //...
        fdt.PrimaryKey = new [] { fdt.Columns[0] };
        return fdt;
    }
   
    // ToDo implement other properties
    // It is straight forward, just have a look at how it's done with the other providers
}
You need to throw in the created FeatureDataTable on the GetFeature and ExecuteIntersectionQuery functions
and fill it.

On which occasion do you need the ID of the cam?
Editor
Jun 6, 2013 at 2:06 PM
I thought I would need the ID of the object if I were to use the ' GetGeometriesbyId ' function of the geometries provider.

I guess if I'm using a custom provider then I can jsut override the GetGeometriesbyId method and make sure I return the object where camId matches.

So with a custom provider, when the coord conversion overwrites the geom, it effectively just updates it, but leaves all the other columns in the feature datatable intact (so all the object data would still be associated with the new geom)?

Thanks for your help.

Rob
Coordinator
Jun 6, 2013 at 2:21 PM
Doesn't your cam object have an id of its own?
If you apply a coordinate transform the other data is not changed
Editor
Jun 6, 2013 at 2:47 PM
It can have an Id (doesn't at present but I can just add an int property). But how would the GetGeometriesById know to use that property?

What I mean is that at this point

var myPoint = gf.CreatePoint(new Coordinate(cam.lon,cam.lat));
           cam.myGeom = myPoint;

           myPoint.UserData = cam;

           geomColl.Add(myPoint);
I set my object to be the userdata to so that during rendering I can access some properties, I would have thought I could have added this

myPoint.Id = cam.Id;

Then I would be able to call

DataProvider.GetGeometriesById(myCam.Id).Geometry = newLocation;

Thanks
Coordinator
Jun 7, 2013 at 7:35 AM
Edited Jun 7, 2013 at 9:53 AM
DataProvider.GetGeometriesById(myCam.Id).Geometry = newLocation;
This definately won't work, at least it is a bad design choice.
you would have to cast your IProvider to the actual type and use the List of cam objects to change the geometry.

Or you create an IWriteableProvider interface that has some Update, Add, Delete functionality, e.g.
public interface IWriteableProvider : IProvider
{
    Update(IEnumerable<FeatureDataRow> features)
    Insert(IEnumerable<FeatureDataRow> features)
    Delete(IEnumerable<FeatureDataRow> features)
}