Hello,
I want to make a ArcGIS map in Unity with C++. Because with this instead of the Map Creator i can change the visibility of layers in the play modus i read. I follow the tutorial : https://developers.arcgis.com/unity/maps/tutorials/display-a-map-api/#prepare-the-script
And this i my code now:
using Esri.ArcGISMapsSDK.Components;
using Esri.ArcGISMapsSDK.Samples.Components;
using Esri.ArcGISMapsSDK.Utils.GeoCoord;
using Esri.GameEngine.Extent;
using Esri.GameEngine.Geometry;
using Esri.Unity;
using UnityEngine;
using System;
[ExecuteAlways]
public string APIKey = "";
private ArcGISMapComponent arcGISMapComponent;
private ArcGISPoint geographicCoordinates = new ArcGISPoint(-74.054921, 40.691242, 3000, ArcGISSpatialReference.WGS84());
private void CreateArcGISMapComponent()
{
arcGISMapComponent = FindObjectOfType<ArcGISMapComponent>();
if (!arcGISMapComponent)
{
var arcGISMapGameObject = new GameObject("ArcGISMap");
arcGISMapComponent = arcGISMapGameObject.AddComponent<ArcGISMapComponent>();
}
arcGISMapComponent.OriginPosition = geographicCoordinates;
arcGISMapComponent.MapType = Esri.GameEngine.Map.ArcGISMapType.Local;
arcGISMapComponent.MapTypeChanged += new ArcGISMapComponent.MapTypeChangedEventHandler(CreateArcGISMap);
}
public void CreateArcGISMap()
{
var arcGISMap = new Esri.GameEngine.Map.ArcGISMap(arcGISMapComponent.MapType);
arcGISMap.Basemap = Esri.GameEngine.Map.ArcGISBasemap.CreateImagery(APIKey);
arcGISMap.Elevation = new Esri.GameEngine.Map.ArcGISMapElevation(new Esri.GameEngine.Elevation.ArcGISImageElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer", "Elevation", ""));
var layer_1 = new Esri.GameEngine.Layers.ArcGISImageLayer("https://tiles.arcgis.com/tiles/nGt4QxSblgDfeJn9/arcgis/rest/services/UrbanObservatory_NYC_TransitFrequency/MapServer", "MyLayer_1", 1.0f, true, "");
arcGISMap.Layers.Add(layer_1);
var layer_2 = new Esri.GameEngine.Layers.ArcGISImageLayer("https://tiles.arcgis.com/tiles/nGt4QxSblgDfeJn9/arcgis/rest/services/New_York_Industrial/MapServer", "MyLayer_2", 1.0f, true, "");
arcGISMap.Layers.Add(layer_2);
var layer_3 = new Esri.GameEngine.Layers.ArcGISImageLayer("https://tiles.arcgis.com/tiles/4yjifSiIG17X0gW4/arcgis/rest/services/NewYorkCity_PopDensity/MapServer", "MyLayer_3", 1.0f, true, "");
arcGISMap.Layers.Add(layer_3);
var buildingLayer = new Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer("https://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/Buildings_NewYork_17/SceneServer", "Building Layer", 1.0f, true, "");
arcGISMap.Layers.Add(buildingLayer);
var extentCenter = new Esri.GameEngine.Geometry.ArcGISPoint(-74.054921, 40.691242, 3000, ArcGISSpatialReference.WGS84());
var extent = new ArcGISExtentCircle(extentCenter, 100000);
arcGISMap.ClippingArea = extent;
arcGISMapComponent.View.Map = arcGISMap;
}
private ArcGISCameraComponent cameraComponent;
private void CreateArcGISCamera()
{
cameraComponent = Camera.main.gameObject.GetComponent<ArcGISCameraComponent>();
if (!cameraComponent)
{
var cameraGameObject = Camera.main.gameObject;
cameraGameObject.transform.SetParent(arcGISMapComponent.transform, false);
cameraComponent = cameraGameObject.AddComponent<ArcGISCameraComponent>();
cameraGameObject.AddComponent<ArcGISCameraControllerComponent>();
cameraGameObject.AddComponent<ArcGISRebaseComponent>();
}
var cameraLocationComponent = cameraComponent.GetComponent<ArcGISLocationComponent>();
if (!cameraLocationComponent)
{
cameraLocationComponent = cameraComponent.gameObject.AddComponent<ArcGISLocationComponent>();
cameraLocationComponent.Position = geographicCoordinates;
cameraLocationComponent.Rotation = new ArcGISRotation(55, 58, 0);
}
}
private void Start()
{
CreateArcGISMapComponent();
CreateArcGISCamera();
CreateSkyComponent();
CreateArcGISMap();
}
private void CreateSkyComponent()
{
#if USE_HDRP_PACKAGE
var currentSky = FindObjectOfType<UnityEngine.Rendering.Volume>();
if (currentSky)
{
ArcGISSkyRepositionComponent skyComponent = currentSky.gameObject.GetComponent<ArcGISSkyRepositionComponent>();
if (!skyComponent)
{
skyComponent = currentSky.gameObject.AddComponent<ArcGISSkyRepositionComponent>();
}
if (!skyComponent.arcGISMapComponent)
{
skyComponent.arcGISMapComponent = arcGISMapComponent;
}
if (!skyComponent.CameraComponent)
{
skyComponent.CameraComponent = cameraComponent;
}
}
#endif
}
And get this errors:
Who can help me a bit with this?
Best regards
Solved! Go to Solution.
Hey I ran into a similar problem to you but I was able to get around it. The way got it to work probably isn't best practice however so i am very open to feedback. First I declared the public layer at the very beginning of the map creator script:
public Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer layer_1;
In the CreateArcGISMap function, I didn't declare the layer as a variable.
layer_1 = new Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer("https://tiles.arcgis.com/tiles/hMKr5amzqrWbbTo8/arcgis/rest/services/IncomePerCap_low_elevation/SceneServer", "Income Per Capita low extrusion", 1.0f, true, "");
And then I wrote a function within my map creator script (not a new script like you have done) that is used to toggle the layers on and off.
public void ToggleIncome()
{
if (layer_1_visibility == true)
{
Debug.Log("Remove Layer 1");
arcGISMap.Layers.Remove(arcGISMap.Layers.IndexOf(layer_1));
layer_1_visibility = false;
Debug.Log("layer_1_visibility" + layer_1_visibility);
return;
}
if (layer_1_visibility == false)
{
Debug.Log("add Layer 1");
arcGISMap.Layers.Add(layer_1);
layer_1_visibility = true;
Debug.Log("layer_1_visibility" + layer_1_visibility);
return;
}
}
This for the most part has worked fine for me to use buttons to toggle layers on and off (except when sideloading onto quest 2 which results in some glitching of layer)
Below is my full segment of the map creator script :
using Esri.ArcGISMapsSDK.Components;
using Esri.ArcGISMapsSDK.Samples.Components;
using Esri.ArcGISMapsSDK.Utils.GeoCoord;
using Esri.GameEngine.Extent;
using Esri.GameEngine.Geometry;
using Esri.Unity;
using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
using System;
[ExecuteAlways]
public class ArcGISMapCreator : MonoBehaviour
{
public string APIKey = "";
public Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer layer_1;
public Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer layer_2;
public Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer layer_3;
public Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer layer_4;
public bool layer_1_visibility = false;
public bool layer_2_visibility = false;
public bool layer_3_visibility = false;
public bool layer_4_visibility = false;
public Esri.GameEngine.Map.ArcGISMap arcGISMap;
public ArcGISMapComponent arcGISMapComponent;
public ArcGISPoint geographicCoordinates = new ArcGISPoint(-118.282390197517, 33.9298048523834, 500, ArcGISSpatialReference.WGS84());
private void Start()
{
CreateArcGISMapComponent();
CreateArcGISCamera();
CreateArcGISMap();
Debug.Log("void start is workign");
}
private void CreateArcGISMapComponent()
{
arcGISMapComponent = FindObjectOfType<ArcGISMapComponent>();
if (!arcGISMapComponent)
{
var arcGISMapGameObject = new GameObject("ArcGISMap");
arcGISMapComponent = arcGISMapGameObject.AddComponent<ArcGISMapComponent>();
}
arcGISMapComponent.OriginPosition = geographicCoordinates;
arcGISMapComponent.MapType = Esri.GameEngine.Map.ArcGISMapType.Local;
arcGISMapComponent.MapTypeChanged += new ArcGISMapComponent.MapTypeChangedEventHandler(CreateArcGISMap);
}
public void CreateArcGISMap()
{
arcGISMap = new Esri.GameEngine.Map.ArcGISMap(arcGISMapComponent.MapType);
arcGISMap.Basemap = Esri.GameEngine.Map.ArcGISBasemap.CreateImagery(APIKey);
arcGISMap.Elevation = new Esri.GameEngine.Map.ArcGISMapElevation(new Esri.GameEngine.Elevation.ArcGISImageElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer", "Elevation", ""));
layer_1 = new Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer("https://tiles.arcgis.com/tiles/hMKr5amzqrWbbTo8/arcgis/rest/services/IncomePerCap_low_elevation/SceneServer", "Income Per Capita low extrusion", 1.0f, true, "");
// arcGISMap.Layers.Add(layer_1);
layer_2 = new Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer("https://tiles.arcgis.com/tiles/hMKr5amzqrWbbTo8/arcgis/rest/services/MostCommonRaceOrEthnicity/SceneServer", "Most Common Race or Ethnicity", 1.0f, true, "");
// arcGISMap.Layers.Add(layer_2);
layer_3 = new Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer("https://tiles.arcgis.com/tiles/hMKr5amzqrWbbTo8/arcgis/rest/services/LA_oilwell_locations/SceneServer", "3D Oil Well Locations", 1.0f, true, "");
// arcGISMap.Layers.Add(layer_3);
layer_4 = new Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer("https://tiles.arcgis.com/tiles/hMKr5amzqrWbbTo8/arcgis/rest/services/CurrentAsthma/SceneServer", "Current Asthma Percentage", 1.0f, true, "");
// arcGISMap.Layers.Add(layer_4);
var extentCenter = new Esri.GameEngine.Geometry.ArcGISPoint(-118.282390197517, 33.9298048523834, 20, ArcGISSpatialReference.WGS84());
var extent = new ArcGISExtentCircle(extentCenter, 40000);
arcGISMap.ClippingArea = extent;
arcGISMapComponent.View.Map = arcGISMap;
Debug.Log("Create GIS map running");
}
private ArcGISCameraComponent cameraComponent;
private void CreateArcGISCamera()
{
cameraComponent = Camera.main.gameObject.GetComponent<ArcGISCameraComponent>();
if (!cameraComponent)
{
var cameraGameObject = Camera.main.gameObject;
cameraGameObject.transform.SetParent(arcGISMapComponent.transform, false);
cameraComponent = cameraGameObject.AddComponent<ArcGISCameraComponent>();
cameraGameObject.AddComponent<ArcGISCameraControllerComponent>();
cameraGameObject.AddComponent<ArcGISRebaseComponent>();
}
var cameraLocationComponent = cameraComponent.GetComponent<ArcGISLocationComponent>();
if (!cameraLocationComponent)
{
cameraLocationComponent = cameraComponent.gameObject.AddComponent<ArcGISLocationComponent>();
// cameraLocationComponent.Position = geographicCoordinates;
cameraLocationComponent.Position = geographicCoordinates =new ArcGISPoint(-118.282390197517, 33.9298048523834, 0, ArcGISSpatialReference.WGS84());
new ArcGISPoint(-118.282390197517, 33.9298048523834, 500, ArcGISSpatialReference.WGS84());
cameraLocationComponent.Rotation = new ArcGISRotation(0, 43.75782, 0);
}
}
public void ToggleIncome()
{
if (layer_1_visibility == true)
{
Debug.Log("Remove Layer 1");
arcGISMap.Layers.Remove(arcGISMap.Layers.IndexOf(layer_1));
layer_1_visibility = false;
Debug.Log("layer_1_visibility" + layer_1_visibility);
return;
}
if (layer_1_visibility == false)
{
Debug.Log("add Layer 1");
arcGISMap.Layers.Add(layer_1);
layer_1_visibility = true;
Debug.Log("layer_1_visibility" + layer_1_visibility);
return;
}
}
public void MostCommonRace()
{
if (layer_2_visibility == true)
{
Debug.Log("Remove Layer 2");
arcGISMap.Layers.Remove(arcGISMap.Layers.IndexOf(layer_2));
layer_2_visibility = false;
return;
}
if (layer_2_visibility == false)
{
Debug.Log("add Layer 2");
arcGISMap.Layers.Add(layer_2);
layer_2_visibility = true;
return;
}
}
public void WellLocation()
{
if (layer_3_visibility == true)
{
Debug.Log("Remove Layer 3");
arcGISMap.Layers.Remove(arcGISMap.Layers.IndexOf(layer_3));
layer_3_visibility = false;
return;
}
if (layer_3_visibility == false)
{
Debug.Log("add Layer 3");
arcGISMap.Layers.Add(layer_3);
layer_3_visibility = true;
return;
}
}
public void Asthma()
{
if (layer_4_visibility == true)
{
Debug.Log("Remove Layer 4");
arcGISMap.Layers.Remove(arcGISMap.Layers.IndexOf(layer_4));
layer_4_visibility = false;
return;
}
if (layer_4_visibility == false)
{
Debug.Log("add Layer 4");
arcGISMap.Layers.Add(layer_4);
layer_4_visibility = true;
return;
}
}
}
Hello, I find the problem. I was missing:
public class ArcGIS_map : MonoBehaviour
{
In the top of the script above the APIkey.
But i have still a problem with a button to turn of a layer. In the ArcGIS map script in the Main Camera i set laag_2.
The layer is visible when i hit play. On the button i add the script Remove_Layer, but in the Onclick part of the button the RemoveLayer() function is missing. I get a error. I think the scripts can't find each other.
Hey I ran into a similar problem to you but I was able to get around it. The way got it to work probably isn't best practice however so i am very open to feedback. First I declared the public layer at the very beginning of the map creator script:
public Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer layer_1;
In the CreateArcGISMap function, I didn't declare the layer as a variable.
layer_1 = new Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer("https://tiles.arcgis.com/tiles/hMKr5amzqrWbbTo8/arcgis/rest/services/IncomePerCap_low_elevation/SceneServer", "Income Per Capita low extrusion", 1.0f, true, "");
And then I wrote a function within my map creator script (not a new script like you have done) that is used to toggle the layers on and off.
public void ToggleIncome()
{
if (layer_1_visibility == true)
{
Debug.Log("Remove Layer 1");
arcGISMap.Layers.Remove(arcGISMap.Layers.IndexOf(layer_1));
layer_1_visibility = false;
Debug.Log("layer_1_visibility" + layer_1_visibility);
return;
}
if (layer_1_visibility == false)
{
Debug.Log("add Layer 1");
arcGISMap.Layers.Add(layer_1);
layer_1_visibility = true;
Debug.Log("layer_1_visibility" + layer_1_visibility);
return;
}
}
This for the most part has worked fine for me to use buttons to toggle layers on and off (except when sideloading onto quest 2 which results in some glitching of layer)
Below is my full segment of the map creator script :
using Esri.ArcGISMapsSDK.Components;
using Esri.ArcGISMapsSDK.Samples.Components;
using Esri.ArcGISMapsSDK.Utils.GeoCoord;
using Esri.GameEngine.Extent;
using Esri.GameEngine.Geometry;
using Esri.Unity;
using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
using System;
[ExecuteAlways]
public class ArcGISMapCreator : MonoBehaviour
{
public string APIKey = "";
public Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer layer_1;
public Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer layer_2;
public Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer layer_3;
public Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer layer_4;
public bool layer_1_visibility = false;
public bool layer_2_visibility = false;
public bool layer_3_visibility = false;
public bool layer_4_visibility = false;
public Esri.GameEngine.Map.ArcGISMap arcGISMap;
public ArcGISMapComponent arcGISMapComponent;
public ArcGISPoint geographicCoordinates = new ArcGISPoint(-118.282390197517, 33.9298048523834, 500, ArcGISSpatialReference.WGS84());
private void Start()
{
CreateArcGISMapComponent();
CreateArcGISCamera();
CreateArcGISMap();
Debug.Log("void start is workign");
}
private void CreateArcGISMapComponent()
{
arcGISMapComponent = FindObjectOfType<ArcGISMapComponent>();
if (!arcGISMapComponent)
{
var arcGISMapGameObject = new GameObject("ArcGISMap");
arcGISMapComponent = arcGISMapGameObject.AddComponent<ArcGISMapComponent>();
}
arcGISMapComponent.OriginPosition = geographicCoordinates;
arcGISMapComponent.MapType = Esri.GameEngine.Map.ArcGISMapType.Local;
arcGISMapComponent.MapTypeChanged += new ArcGISMapComponent.MapTypeChangedEventHandler(CreateArcGISMap);
}
public void CreateArcGISMap()
{
arcGISMap = new Esri.GameEngine.Map.ArcGISMap(arcGISMapComponent.MapType);
arcGISMap.Basemap = Esri.GameEngine.Map.ArcGISBasemap.CreateImagery(APIKey);
arcGISMap.Elevation = new Esri.GameEngine.Map.ArcGISMapElevation(new Esri.GameEngine.Elevation.ArcGISImageElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer", "Elevation", ""));
layer_1 = new Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer("https://tiles.arcgis.com/tiles/hMKr5amzqrWbbTo8/arcgis/rest/services/IncomePerCap_low_elevation/SceneServer", "Income Per Capita low extrusion", 1.0f, true, "");
// arcGISMap.Layers.Add(layer_1);
layer_2 = new Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer("https://tiles.arcgis.com/tiles/hMKr5amzqrWbbTo8/arcgis/rest/services/MostCommonRaceOrEthnicity/SceneServer", "Most Common Race or Ethnicity", 1.0f, true, "");
// arcGISMap.Layers.Add(layer_2);
layer_3 = new Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer("https://tiles.arcgis.com/tiles/hMKr5amzqrWbbTo8/arcgis/rest/services/LA_oilwell_locations/SceneServer", "3D Oil Well Locations", 1.0f, true, "");
// arcGISMap.Layers.Add(layer_3);
layer_4 = new Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer("https://tiles.arcgis.com/tiles/hMKr5amzqrWbbTo8/arcgis/rest/services/CurrentAsthma/SceneServer", "Current Asthma Percentage", 1.0f, true, "");
// arcGISMap.Layers.Add(layer_4);
var extentCenter = new Esri.GameEngine.Geometry.ArcGISPoint(-118.282390197517, 33.9298048523834, 20, ArcGISSpatialReference.WGS84());
var extent = new ArcGISExtentCircle(extentCenter, 40000);
arcGISMap.ClippingArea = extent;
arcGISMapComponent.View.Map = arcGISMap;
Debug.Log("Create GIS map running");
}
private ArcGISCameraComponent cameraComponent;
private void CreateArcGISCamera()
{
cameraComponent = Camera.main.gameObject.GetComponent<ArcGISCameraComponent>();
if (!cameraComponent)
{
var cameraGameObject = Camera.main.gameObject;
cameraGameObject.transform.SetParent(arcGISMapComponent.transform, false);
cameraComponent = cameraGameObject.AddComponent<ArcGISCameraComponent>();
cameraGameObject.AddComponent<ArcGISCameraControllerComponent>();
cameraGameObject.AddComponent<ArcGISRebaseComponent>();
}
var cameraLocationComponent = cameraComponent.GetComponent<ArcGISLocationComponent>();
if (!cameraLocationComponent)
{
cameraLocationComponent = cameraComponent.gameObject.AddComponent<ArcGISLocationComponent>();
// cameraLocationComponent.Position = geographicCoordinates;
cameraLocationComponent.Position = geographicCoordinates =new ArcGISPoint(-118.282390197517, 33.9298048523834, 0, ArcGISSpatialReference.WGS84());
new ArcGISPoint(-118.282390197517, 33.9298048523834, 500, ArcGISSpatialReference.WGS84());
cameraLocationComponent.Rotation = new ArcGISRotation(0, 43.75782, 0);
}
}
public void ToggleIncome()
{
if (layer_1_visibility == true)
{
Debug.Log("Remove Layer 1");
arcGISMap.Layers.Remove(arcGISMap.Layers.IndexOf(layer_1));
layer_1_visibility = false;
Debug.Log("layer_1_visibility" + layer_1_visibility);
return;
}
if (layer_1_visibility == false)
{
Debug.Log("add Layer 1");
arcGISMap.Layers.Add(layer_1);
layer_1_visibility = true;
Debug.Log("layer_1_visibility" + layer_1_visibility);
return;
}
}
public void MostCommonRace()
{
if (layer_2_visibility == true)
{
Debug.Log("Remove Layer 2");
arcGISMap.Layers.Remove(arcGISMap.Layers.IndexOf(layer_2));
layer_2_visibility = false;
return;
}
if (layer_2_visibility == false)
{
Debug.Log("add Layer 2");
arcGISMap.Layers.Add(layer_2);
layer_2_visibility = true;
return;
}
}
public void WellLocation()
{
if (layer_3_visibility == true)
{
Debug.Log("Remove Layer 3");
arcGISMap.Layers.Remove(arcGISMap.Layers.IndexOf(layer_3));
layer_3_visibility = false;
return;
}
if (layer_3_visibility == false)
{
Debug.Log("add Layer 3");
arcGISMap.Layers.Add(layer_3);
layer_3_visibility = true;
return;
}
}
public void Asthma()
{
if (layer_4_visibility == true)
{
Debug.Log("Remove Layer 4");
arcGISMap.Layers.Remove(arcGISMap.Layers.IndexOf(layer_4));
layer_4_visibility = false;
return;
}
if (layer_4_visibility == false)
{
Debug.Log("add Layer 4");
arcGISMap.Layers.Add(layer_4);
layer_4_visibility = true;
return;
}
}
}
Thanks for your answer. Now i know how to make the map and layers public, without to activate the CreateArcGisMap function to update my layers. That was now my solution with toggles and after that i made a button to update the map. But your solution is better. But i don't have a lot of glitsing, maybe my map is smaller.
Only i have another problem with my extent. Image tile layers going outside of my circle 1000 m extent. Do you also have that problem? Bug?
Hey yes I initially did have an issue with the extent. The way I got around it was by adjusting the extent values in the inspector on the ArcGISMap object within the ArcGIS Map component to be the same as what I declared in the code. This should make the extent work.
I am curious what sort of glitching you are having in your map because am having issues currently with glitching but only when I create maps using C# API?
That doesn't work for me > Extent.
I don't know if a have glitching when i use the Mapcreator UI. In ArcGIS Pro i also make Multipatch layers and use the Layer 3D tool to make 3D layers. And the i Share the Map as Scene Map and then get the https links in My Content of ArcGIS Online. Maybe its glitching because of layers lies on top of each other. Maybe you can give the layers a little elevation height difference in AP.