Select to view content in your preferred language

AGSPoint Issue - PointWithX Not Accepting Coordinates

4251
5
Jump to solution
04-07-2014 07:13 AM
DarrenSulfridge
Emerging Contributor
I'm sure this is something simple I'm missing, but I'm just not seeing it. I'm trying to add a single point abject to a graphics layer and no matter what I do, the point is always showing up just off the western coast of Africa (basically, center of the world map). This is under 10.2 and Xcode 5.1.

My code to do this is as follows:

- (void) plotPoints {     //--- Add a sample point. ---//     //--- First, set up a symbol for the point. ---//     AGSSimpleMarkerSymbol *myMarkerSymbol = [AGSSimpleMarkerSymbol simpleMarkerSymbol];          myMarkerSymbol.color = [UIColor blueColor];          //--- Now, create a point for the graphic to be drawn. ---//     AGSPoint *myPoint = [AGSPoint pointWithX:-96.6477 y:33.0477 spatialReference:self.mapView.spatialReference];          //--- Create a graphic using the marker and point. ---//     AGSGraphic *myGraphic = [AGSGraphic graphicWithGeometry:myPoint symbol:myMarkerSymbol attributes:nil];          //--- Add the graphic to the graphic layer. ---//     [self.graphicsLayer addGraphic:myGraphic];    } 


This is being called from my viewDidLoad after opening a base map (ArcGIS Online) and adding the graphic layer. The point displays fine with the exception of the location never changing. Is there somehow a difference in the spatialReference that is causing the coordinates to be thrown out?

Edit: After further playing around, it does appear that this is an issue with the coordinate system between the map and the coordinates I'm providing. How do I go about converting from X/Y to whatever units the map is using?

Edit 2: I found a prior post that had the following algorithm in it that has my point in the proper area now.

    //convert longitude and latitude to map point X Y     double mercatorX = longitude * 0.017453292519943295 * 6378137.0;     double a = latitude * 0.017453292519943295;     double mercatorY = 3189068.5 * log((1.0 + sin(a))/(1.0 - sin(a)));


This will get me where I need to be, but it seems like there should be a built in method to do this. I'd prefer to use something a bit more standard if possible.
0 Kudos
1 Solution

Accepted Solutions
DiveshGoyal
Esri Regular Contributor
Darren,

Let me try to explain.

You are trying to add a graphic on a map. You are assigning the graphic a point geometry whose x & y coordinates are in lat/long format, basically decimal degrees. This implies that your point geometry is WGS84 spatial reference.

The map you are using is probably in WebMercator spatial reference. The x& y coordinates on this map are expressed in meter values. Therefore, the lat/long values you are using for your graphic will not show up in the right location on the map. They will, as you observed, be somewhere near the center.

To get this all to work, you need to perform one additional step of projecting your point geometry which uses WGS84 spatial reference into Web Mercator. You can then use this projected result in your graphic and place it correctly on the map. The Runtime SDK does not automatically project geometries for you.

    float longitude = -96.6477;     float latitude = 33.0477;   AGSPoint *wgs84Point = [AGSPoint pointWithX:longitude y:latitude spatialReference:[AGSSpatialReference wgs84SpatialReference]];  //This example shows using GeometryEngine to project, but  you can also AGSGeometryGeographicToWebMercator() function //See https://developers.arcgis.com/ios/api-reference/_a_g_s_geometry_8h.html#ac501960bbf7012239968ba9107935430   AGSGeometryEngine* ge = [AGSGeometryEngine defaultGeometryEngine]; AGSPoint* webmercatorPoint = [ge projectGeometry:wgs84Point toSpatialReference:[AGSSpatialReference webMercatorSpatialReference    ]];   AGSGraphic *myGraphic = [AGSGraphic graphicWithGeometry:webmercatorPoint symbol:myMarkerSymbol attributes:nil]; ...

View solution in original post

0 Kudos
5 Replies
NimeshJarecha
Esri Regular Contributor
You can use AGSGeometryGeographicToWebMercator() function to cover WGS 1984 coordinate to web mercator. Also, you can use AGSGeometryEngine's projectGeometry:toSpatialReference: method to project geometries in different spatial reference.

Hope this helps!

Regards,
Nimesh
0 Kudos
YueWu1
by Esri Regular Contributor
Esri Regular Contributor
Hi there,

Seems that your base map or map's spatial reference is not WGS1984

Try AGSPoint *myPoint = [AGSPoint pointWithX:*** y:*** spatialReference:[AGSSpatialReference wgs84SpatialReference]];

You can also check this link about the AGSPoint setting:
https://github.com/Esri/quickstart-map-ios/blob/master/Lib/EsriQuickStartLib/AGS%20Categories/Genera...
0 Kudos
DarrenSulfridge
Emerging Contributor
You can use AGSGeometryGeographicToWebMercator() function to cover WGS 1984 coordinate to web mercator. Also, you can use AGSGeometryEngine's projectGeometry:toSpatialReference: method to project geometries in different spatial reference.

Hope this helps!

Regards,
Nimesh


I'm finally getting back to working on this and unfortunately, I'm not making any headway with your suggestion. Is there an example of using this on an AGS point somewhere?

My current code is:

- (void) plotPoints
{
    //--- Add a sample point. ---//
    //--- First, set up a symbol for the point. ---//
    AGSSimpleMarkerSymbol *myMarkerSymbol = [AGSSimpleMarkerSymbol simpleMarkerSymbol];
    
    myMarkerSymbol.color = [UIColor greenColor];
    
    //--- Sample lat/long to test with. ---//
    float longitude = -96.6477;
    float latitude = 33.0477;
    
    //--- Convert longitude and latitude to map point X Y ---//
    double mercatorX = longitude * 0.017453292519943295 * 6378137.0;
    double a = latitude * 0.017453292519943295;
    double mercatorY = 3189068.5 * log((1.0 + sin(a))/(1.0 - sin(a)));
    
    //--- Now, create a point for the graphic to be drawn. ---//
    AGSPoint *myPoint = [AGSPoint pointWithX:mercatorX y:mercatorY spatialReference:self.mapView.spatialReference];
    
    //--- Create a graphic using the marker and point. ---//
    AGSGraphic *myGraphic = [AGSGraphic graphicWithGeometry:myPoint symbol:myMarkerSymbol attributes:nil];
    
    //--- Add the graphic to the graphic layer. ---//
    [self.graphicsLayer addGraphic:myGraphic];
    
    //--- Force a better initial view for testing. ---//
    AGSMutableEnvelope *extent = [self.graphicsLayer.fullEnvelope mutableCopy];
    [extent expandByFactor:1.5];
    [self.mapView zoomToEnvelope:extent animated:YES];
    
}


No matter what I set the spatial reference to in the call to pointwithx, I have to use the manual conversion and not the direct lat/long values. Shouldn't this change where the point is drawn, even if it is still incorrectly placed? I guess I really don't understand what is going on at all in the ESRI side of the code.
0 Kudos
DiveshGoyal
Esri Regular Contributor
Darren,

Let me try to explain.

You are trying to add a graphic on a map. You are assigning the graphic a point geometry whose x & y coordinates are in lat/long format, basically decimal degrees. This implies that your point geometry is WGS84 spatial reference.

The map you are using is probably in WebMercator spatial reference. The x& y coordinates on this map are expressed in meter values. Therefore, the lat/long values you are using for your graphic will not show up in the right location on the map. They will, as you observed, be somewhere near the center.

To get this all to work, you need to perform one additional step of projecting your point geometry which uses WGS84 spatial reference into Web Mercator. You can then use this projected result in your graphic and place it correctly on the map. The Runtime SDK does not automatically project geometries for you.

    float longitude = -96.6477;     float latitude = 33.0477;   AGSPoint *wgs84Point = [AGSPoint pointWithX:longitude y:latitude spatialReference:[AGSSpatialReference wgs84SpatialReference]];  //This example shows using GeometryEngine to project, but  you can also AGSGeometryGeographicToWebMercator() function //See https://developers.arcgis.com/ios/api-reference/_a_g_s_geometry_8h.html#ac501960bbf7012239968ba9107935430   AGSGeometryEngine* ge = [AGSGeometryEngine defaultGeometryEngine]; AGSPoint* webmercatorPoint = [ge projectGeometry:wgs84Point toSpatialReference:[AGSSpatialReference webMercatorSpatialReference    ]];   AGSGraphic *myGraphic = [AGSGraphic graphicWithGeometry:webmercatorPoint symbol:myMarkerSymbol attributes:nil]; ...
0 Kudos
DarrenSulfridge
Emerging Contributor
I just got a chance to try this and it does appear to be working! I'm getting a warning that the call to projectgeometry is returning a type AGSGeometry rather than an AGSPoint, but it is still putting the point in the proper location.

One bit of oddness. If I try to pull the current spatial reference from the map view instead of hardcoding it to web mercator, it will not draw my point. It seems like it's putting the point in the proper location as the extent is identical to what I would get with the hard coded spatial reference, but it's not showing the point. It's not a high deal, I just don't quite understand why it's doing that.

I do appreciate the assistance!
Darren
0 Kudos