# How to move a Polygon from one Point to another Point using it's center Point

682
4
11-03-2020 12:32 AM
New Contributor III

Hello Esri community,

I'm working on a Java desktop application using ArcGIS Java runtime SDK v100.7.0. In my MapView GraphicsOverlay, I've added a circular Polygon graphic using ellipseGeodesic(GeodesicEllipseParameters parameters) method keeping it's center point as my ship/vessel's location Point. Now as my ship moves, I would like this Polygon to move with it as well. I want to know if there is any convenient way to move a Polygon Geometry from one Point to another by just specifying the next given Point as center to this Polygon. The vessel and the circular Polygon graphic are manipulated by another class in my code which doesn't have access to the circle's radius or such parameters which can be used to draft a new Polygon geometry so I'd want to manipulate and move the same object (using it's center Point only) without replacing with a new one.

1 Solution

Accepted Solutions
Esri Regular Contributor

There is no API for moving a polygon as they are immutable.  You have to create a new one which is the workflow I was showing in my code example.  Remember that Graphics can be updated with a new geometry, which is how you create an updating graphics view of your world.

So if each ship you are tracking has a different radius, you need to store this somewhere.  Although in my example I've shown a graphic consisting of a geometry and a symbol, they can also have attributes which could be used to store your extra information.

You could look into using the moveGeodesic methods to help you constrict a new geometry from an existing set of points from an old geometry GeometryEngine (ArcGIS Runtime SDK for Java 100.9.0) , but its probably easer to call your ellipseGeodesic method again.

4 Replies
Esri Regular Contributor

Geometries are immutable so you can't move them.  Instead you just create a new one and its very easy to apply a new geometry to an existing graphic and hence move it.

I've had a go at this using a point and a polygon which I've also created with ellipseGeodesic.  It looked like this:

My app had some class members to track my ship

`private GraphicsOverlay dynamicGraphicsLayer;private double xPos=0, yPos=0; // current location of my shipprivate Graphic shipGraphic; // graphic for shipprivate Graphic shipBufferGraphic; // graphic for buffer around ship`

A method to create my buffer / ellipse

`public Polygon generateBuffer(Point shipPosition) {  Polygon buffer = null;  GeodesicEllipseParameters parameters = new GeodesicEllipseParameters();  parameters.setCenter(shipPosition);  parameters.setSemiAxis1Length(500);  parameters.setSemiAxis2Length(500);  parameters.setMaxSegmentLength(5);  buffer = (Polygon) GeometryEngine.ellipseGeodesic(parameters);  return buffer;}`

The initial position was drawn like this:

`// create a dynamic graphics layerdynamicGraphicsLayer =   new GraphicsOverlay(GraphicsOverlay.RenderingMode.DYNAMIC);mapView.getGraphicsOverlays().add(dynamicGraphicsLayer);// symbolsSimpleLineSymbol bufferSymbol =   new SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, 0xFF00FF00, 3);SimpleMarkerSymbol shipSymbol =   new SimpleMarkerSymbol(SimpleMarkerSymbol.Style.CIRCLE, 0xFFFF0000, 10);// geometriesPoint shipPosition = new Point(xPos,yPos, SpatialReferences.getWebMercator());Polygon shipBuffer = generateBuffer(shipPosition);// initial graphics showing ship and buffershipGraphic = new Graphic(shipPosition, shipSymbol);shipBufferGraphic = new Graphic(shipBuffer, bufferSymbol);// adding graphics to graphics layerdynamicGraphicsLayer.getGraphics().add(shipGraphic);dynamicGraphicsLayer.getGraphics().add(shipBufferGraphic);`

Then I had a button on my app to move the position of the ship slightly

`Button addGraphics = new Button("move ship");addGraphics.setOnAction(event -> {  // move the ship  xPos = xPos + 50;  yPos = yPos + 50;  Point newLocation = new Point(xPos, yPos, SpatialReferences.getWebMercator());  // update the graphics location  moveShip(newLocation);});`

Which in turn calls this simple code to apply the new geometries to your existing graphics

`public void moveShip(Point newLocation) {  shipGraphic.setGeometry(newLocation);  shipBufferGraphic.setGeometry(generateBuffer(newLocation));}`

This is a very common workflow and even if you use it for updating thousands of graphics it works well.

Does this help?

New Contributor III

While I really appreciate that you were kind enough to share the code and thanks for that however, I just wanted to know if a polygon geometry could be moved or not but since you said that geometries are immutable that means i have to create a new one without keeping the same geometry. The problem here is that The semi axis lengths you have set are constant while it is variable in my case. Also my coded class method that is responsible for moving the ship does not have access to the radius (semi axis length) so i have to do something about it. There is another similar scenario where I'd need to implement it for many other vessels on the map without fetching their circle radius keeping this moving logic independent of the radius values for each of those vessels but I have to track those too. Thanks for your response.

Esri Regular Contributor

There is no API for moving a polygon as they are immutable.  You have to create a new one which is the workflow I was showing in my code example.  Remember that Graphics can be updated with a new geometry, which is how you create an updating graphics view of your world.

So if each ship you are tracking has a different radius, you need to store this somewhere.  Although in my example I've shown a graphic consisting of a geometry and a symbol, they can also have attributes which could be used to store your extra information.

You could look into using the moveGeodesic methods to help you constrict a new geometry from an existing set of points from an old geometry GeometryEngine (ArcGIS Runtime SDK for Java 100.9.0) , but its probably easer to call your ellipseGeodesic method again.

New Contributor III

Yes, as you said the Geometry is immutable so we have to add a new Geometry and set it in the given Graphic. I came up with a solution for this and it matches with exactly what you suggested. When one of my class method creates the ship graphic and the circle graphic around it, at that point I put the radius value into the polygon graphic attribute so when my other class method gets this graphic object, I can simply extract the radius attribute from the polygon graphic and create a new polygon using ellipseGeodesic(..) method, which I then set as that graphic's geometry. The main thing is that the Geometry cannot be moved as it's immutable. Your help is appreciated. Thanks.