add image which dynamically changing size when zooming the map

716
4
Jump to solution
01-15-2020 05:23 PM
Kae_WoeiKang
New Contributor II

Hi ArcGIS team,

I've added an Image (example: floor plan) by using PictureMarkerSymbol class; and add the graphic onto map by using GraphicOverlay class.

PictureMarkerSymbol pictureMarkerSymbol = new PictureMarkerSymbol(myImage);
Graphic graphic = new Graphic(polygon.getExtent().getCenter(), pictureMarkerSymbol);

pictureMarkerSymbol.loadAsync();
pictureMarkerSymbol.addDoneLoadingListener(new Runnable() {
@Override
public void run() {
mGraphicsOverlay.getGraphics().add(graphic);
}
});

However, I am facing issue where the image loaded is fixed on its size and not dynamically resize when I zoom in or out of the map. For instance, when I zoom into the map -- the image should be bigger; when I zoom out of the map -- the image should be smaller.

Please advise.

Thanks and best regards,

Kae Woei

0 Kudos
1 Solution

Accepted Solutions
AlanLucas
Esri Contributor

I think you should be able to use reference scale to achieve what you want. The code below displays a PictureMarkerSymbol in a GraphicsOverlay and an keeps it a consistent size on the map (not the screen) when the user zooms in and out. The key things to note are the calls to mMap.setReferenceScale(REFERENCE_SCALE) to set a reference scale for the map, and graphicsOverlay.setScaleSymbols(true) to tell the GraphicsOverlay to honor the map's reference scale.

final double REFERENCE_SCALE = 50000000;

mMap = new ArcGISMap(Basemap.createLightGrayCanvas());

// Set the map's reference scale
mMap.setReferenceScale(REFERENCE_SCALE);
mMapView.setMap(mMap);
mMap.addDoneLoadingListener(() -> {
  logLoadResult("mMap", mMap);

  // Set the map's viewpoint scale to equal the reference scale, so the symbol will

  // display at its authored size
  ListenableFuture<Boolean> future = mMapView.setViewpointScaleAsync(REFERENCE_SCALE);
  future.addDoneListener(() -> {
    try {
      Boolean success = future.get();

      PictureMarkerSymbol symbol = new PictureMarkerSymbol(

          "https://webapps-cdn.esri.com/Apps/MegaMenu/img/logo.jpg");
      Graphic graphic = new Graphic(new Point(0, 0), symbol);
      GraphicsOverlay graphicsOverlay = new GraphicsOverlay();

      // Set the GraphicsOverlay to honor the map's reference scale
      graphicsOverlay.setScaleSymbols(true);

      graphicsOverlay.getGraphics().add(graphic);
      mMapView.getGraphicsOverlays().add(graphicsOverlay);
    } catch (Throwable e) {
      listenableFutureError(e, "setViewpointScaleAsync");
    }
  });
});

View solution in original post

4 Replies
Kae_WoeiKang
New Contributor II

Maybe I should refined my question...

I wish to set the four corners of my image on its corresponding latitude and longitude. 

Example: 

PointCollection coloradoCorners = new PointCollection(SpatialReferences.getWgs84());
coloradoCorners.add(floorPlan.getTopLeft().Longitude, floorPlan.getTopLeft().Latitude);
coloradoCorners.add(floorPlan.getTopRight().Longitude, floorPlan.getTopRight().Latitude);
coloradoCorners.add(floorPlan.getBottomLeft().Longitude, floorPlan.getBottomLeft().Latitude);
coloradoCorners.add(floorPlan.getBottomRight().Longitude, floorPlan.getBottomRight().Latitude);

With the assigned locations for these 4 points; the image(floorPlan) will be resized based on user's action (zoom in and out from map).

Meanwhile, I found that PictureFillSymbol might able to serve the purpose of filling the polygon with the picture; but no longer support PictureFillSymbol (Drawable drawable) constructor in 100.7.0 version. URL: PictureFillSymbol | ArcGIS Android 10.2.9 API 

Is there any alternative I can use?

by using google map service, I am able to achieve this by simply set the anchor and position the image. 

GroundOverlay groundoverlay = mMapView.addGroundOverlay(new GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromBitmap(bm))
.anchor(0, 0) //anchor at the topLeft
.position(new LatLng(topLeft.getLatitude(), topLeft.getLongitude()), //position it at the topLeft
topRight.distanceTo(topLeft), //scale by distance between topRight and topLeft
bottomRight.distanceTo(topRight)) //scale by distance between topRight and BottomRight
.bearing(-(90 - topLeft.bearingTo(topRight)))); //rotate by the bearing between topLeft and topRight

I wonder if ESRI has any functions for this purpose? 

0 Kudos
AlanLucas
Esri Contributor

I think you should be able to use reference scale to achieve what you want. The code below displays a PictureMarkerSymbol in a GraphicsOverlay and an keeps it a consistent size on the map (not the screen) when the user zooms in and out. The key things to note are the calls to mMap.setReferenceScale(REFERENCE_SCALE) to set a reference scale for the map, and graphicsOverlay.setScaleSymbols(true) to tell the GraphicsOverlay to honor the map's reference scale.

final double REFERENCE_SCALE = 50000000;

mMap = new ArcGISMap(Basemap.createLightGrayCanvas());

// Set the map's reference scale
mMap.setReferenceScale(REFERENCE_SCALE);
mMapView.setMap(mMap);
mMap.addDoneLoadingListener(() -> {
  logLoadResult("mMap", mMap);

  // Set the map's viewpoint scale to equal the reference scale, so the symbol will

  // display at its authored size
  ListenableFuture<Boolean> future = mMapView.setViewpointScaleAsync(REFERENCE_SCALE);
  future.addDoneListener(() -> {
    try {
      Boolean success = future.get();

      PictureMarkerSymbol symbol = new PictureMarkerSymbol(

          "https://webapps-cdn.esri.com/Apps/MegaMenu/img/logo.jpg");
      Graphic graphic = new Graphic(new Point(0, 0), symbol);
      GraphicsOverlay graphicsOverlay = new GraphicsOverlay();

      // Set the GraphicsOverlay to honor the map's reference scale
      graphicsOverlay.setScaleSymbols(true);

      graphicsOverlay.getGraphics().add(graphic);
      mMapView.getGraphicsOverlays().add(graphicsOverlay);
    } catch (Throwable e) {
      listenableFutureError(e, "setViewpointScaleAsync");
    }
  });
});

View solution in original post

Kae_WoeiKang
New Contributor II

Hi Alan,

Thank you so much for helping and providing a sample codes.

The codes works! This is a great alternative but we hard coded REFERENCE_SCALE. I am thinking of a dynamic method, where there are two or more  difference size images added onto the map.

Anyway, may I know how to calculate/obtain the value of REFERENCE_SCALE?

Thanks and best regards,

Kae Woei

0 Kudos
AlanLucas
Esri Contributor

Hi Kae Woei,

Try removing the line graphicsOverlay.setScaleSymbols(true); in the code above, so the GraphicsOverlay doesn't honor the reference scale. Then zoom the map until the symbol is the correct size on the map. Then set the map's reference scale to the current map scale as follows, and also tell the GraphicsOverlay to start honoring the map's reference scale.

mMap.setReferenceScale(mMapView.getMapScale());
mGraphicsOverlay.setScaleSymbols(true);

Alan