How to switch positions on coordinates

9177
5
Jump to solution
12-11-2015 03:39 AM
ErikNilsson1
New Contributor II

Hi, I would like to create polygons from a field in my GeoEvent Definition called Polygon.

The data is formatted like this:

"57.71127941662247,12.523986568755383 57.635773125999144,12.45961803332399 57.576614311073236,12.436624888552302 57.71127941662247,12.523986568755383"

Ie latitude1,longitude1 latitude2,longitude2 ... latitudeN,longitudeN

I would like it to be:

”[[12.523986568755383, 57.71127941662247],[12.45961803332399, 57.635773125999144],[12.436624888552302, 57.576614311073236], [12.523986568755383, 57.71127941662247]]

Ie [[longitude1, latitude1], [longitude2,latitude2], ... [longitudeN,latitudeN]]

And then map the string to a Geometry field.

Is it possible to construct Regular Expressions in Field calculator to switch the positions of lat and long in a string?

I am not very familiar with RegEx so any help are appriciated.

Having a projection similar to WGS84 but with the latitude coordinat in the first positon and longitude in the second position would be another option but I dont know if it exists?

Edited by RJ Sunderman:

You can work with an event field as a String and use a GeoEvent Field Calculator to add information such as spatial reference to produce a JSON String representation of a Geometry. Look for additional detail on working with Geometries in GeoEvent in 'Appendix A' of the GeoEvent Extension Introduction tutorial. Look for the section titled "Using a Field Calculator Processor to compute a geometry".

Unfortunately, the regular expression support extended by GeoEvent does not support the concept of back references. So you won’t be able to pattern match \([0-9][0-9.]*\)\([0-9][0-9.]*\) and replace the pattern with \2\1 to swap the latitude and longitude. Developing a custom processor using the SDK is probably a better approach than trying to do this using out-of-the-box functionality.

Update 31-March-2016 - RJ Sunderman:

Thanks go to Maarten Tromp for his comments in the thread Swap coordinate pairs in a Polygon

It is indeed possible to use RegEx back references to swap the latitude and longitude values if you use the correct syntax. Within a GeoEvent Field Calcualtor you would use $2$1 (not \2\1 as I originally tried).

0 Kudos
1 Solution

Accepted Solutions
RJSunderman
Esri Regular Contributor

Erik -

I ran across a post from Maarten Tromp​ in the following thread: Swap coordinate pairs in a Polygon. Taking what he suggested, here is an approach you can follow using GeoEvent out-of-the-box without having to resort to developing a custom processor.

Given:  A portion of an input stream with comma separated pairs of coordinate values and a space between each pair of coordinates.

Example:  57.711279,12.523986 57.635773,12.459618 57.576614,12.436624 57.711279,12.523986

First you need to reverse each coordinate pair. I used an Receive JSON on a REST Endpoint input to HTTP/POST the following JSON to a GeoEvent Service:

{
  "trackid": "AA-1234",
  "coordinates": "57.711279,12.523986 57.635773,12.459618 57.576614,12.436624 57.711279,12.523986"
}

Use a Field Calculator processor with the following expression to accomplish this:

Expression:  replaceAll(coordinates,'([-]*[0-9]+\.[0-9]+?),([-]*[0-9]+(\.[0-9]+)?)','$2,$1')

Notice that the regular expression I used supports an optional negative sign in front of each coordinate value. A site you might want to bookmark to learn about and experiment with regular expressions is:  regex101.com

Next you need to replace the literal space between each coordinate pair with a literal string ],[ to format the coordinate values as a set of nested JSON arrays and bracket the beginning and end of the string with [[ and ]]. Note that the RegEx pattern matching the beginning of a line is ^. The RegEx pattern for matching the end of a line is $.

Expression:  replaceAll(coordinates,' ','],[')

Expression:  replaceAll(coordinates,'^','[[')

Expression:  replaceAll(coordinates,'$',']]')

Your GeoEvent Service so far looks like:

Capture.png

And is producing output which looks like:

Capture1.png

Now you need to complete the formatting of your coordinate string to create a string representation of a Geometry. For this step I chose to copy the GeoEvent Definition used by the PolygonCoordinatesFeed input and add a field named GeomString. A Field Maper processor maps the existing coordinates and trackid into the new event structure leaving GeomString unmapped. Another Field Calculator processor will write its result into this new field. I do this so that the Field Calculator can write to an existing field without having to create an event defintion on-the-fly in order to write to a new field.

Here is the expression used in this most recent Field Calculator processor:

'{"rings":[' + coordinates + '],"spatialReference":{"wkid":4326}}'

What I'm doing here is prepending a literal string {"rings":[ to the coordinates value and appending a literal string ],"spatialReference":{"wkid":4326}} to the end of the string.

A final Field Mapper takes the event structure with the string representation of the Geometry and maps it to a field named Geometry. I now have an event with a field named trackid and a field named Geometry which I can send to a stream service to display the Geometry I've computed from the coordinate values received from the original feed. Here's my final GeoEvent Service:

Capture2.png

I've attached an XML export of this configuration for both the 10.3.1 and 10.4 product releases. You will, of course, need to fix any validation errors by publishing your own stream service or switching to use a different output connector if you want to import this configuration.

Hope this information in helpful -

RJ

View solution in original post

5 Replies
ChrisSmith7
Frequent Contributor

You can do this with regex, but, since you aren't familiar with it, it may cause more pain than good. There's an old saying, "I once had a problem I thought I'd solve with regex... Now I have two problems!" That being said, regex is really powerful, just remember when to use it, when not to use it, and always use wisely! You can Google regex testers online for your flavor of regex, e.g. Python, .NET, etc. to help you proof-of-concept something.

In the meantime, try something like this:

Pre-logic:

def updateValue(value):  
    valueArry = value.split(" ")  
    newValueArry = []  
    retVal = "["  
    s = " "  
  
    for latLong in valueArry[:-1]:  
        pairArry = latLong.split(",")  
        newPair = pairArry[1] + "," + pairArry[0]  
        newValueArry.append("[" + newPair + "],")
    else:
        pairArry = latLong.split(",")  
        newPair = pairArry[1] + "," + pairArry[0]  
        newValueArry.append("[" + newPair + "]")
     
    retVal = retVal + s.join(newValueArry)  
    return retVal + "]"  

Polygon =

updateValue( !Polygon! )

UPDATED...

ChrisSmith7
Frequent Contributor

I forgot the last element in the array - I went ahead and updated my answer so it accounts for that. You can make it more elegant, but it should output what you need:

[[12.523986568755383,57.71127941662247], [12.45961803332399,57.635773125999144], [12.436624888552302,57.576614311073236], [12.436624888552302,57.576614311073236]]

ErikNilsson1
New Contributor II

Hi,

Thanks for your answer but it seams like you have been using the ArcGIS desktop Field Calculator (right?) and I needed help with the ArcGIS GeoEvent Extension Field Calculator Processor. I might have been a little bit unclear in my question...

Although I solved the problem by using the ArcGIS GeoEvent SDK and made a Processor in Java based on the samples that are provided with the SDK.

0 Kudos
ChrisSmith7
Frequent Contributor

My apologies, Erik - my brain skipped-over the fact that this was for the GeoEvent Extension Field Calculator. I did some research and found the GitHub - Esri/solutions-geoevent-java · GitHub - it looks like you've already gone down this route...

Sorry again! Debating deleting my answer - maybe it would be helpful for someone with an ArcMap Field Calculator issue down the road, though...

0 Kudos
RJSunderman
Esri Regular Contributor

Erik -

I ran across a post from Maarten Tromp​ in the following thread: Swap coordinate pairs in a Polygon. Taking what he suggested, here is an approach you can follow using GeoEvent out-of-the-box without having to resort to developing a custom processor.

Given:  A portion of an input stream with comma separated pairs of coordinate values and a space between each pair of coordinates.

Example:  57.711279,12.523986 57.635773,12.459618 57.576614,12.436624 57.711279,12.523986

First you need to reverse each coordinate pair. I used an Receive JSON on a REST Endpoint input to HTTP/POST the following JSON to a GeoEvent Service:

{
  "trackid": "AA-1234",
  "coordinates": "57.711279,12.523986 57.635773,12.459618 57.576614,12.436624 57.711279,12.523986"
}

Use a Field Calculator processor with the following expression to accomplish this:

Expression:  replaceAll(coordinates,'([-]*[0-9]+\.[0-9]+?),([-]*[0-9]+(\.[0-9]+)?)','$2,$1')

Notice that the regular expression I used supports an optional negative sign in front of each coordinate value. A site you might want to bookmark to learn about and experiment with regular expressions is:  regex101.com

Next you need to replace the literal space between each coordinate pair with a literal string ],[ to format the coordinate values as a set of nested JSON arrays and bracket the beginning and end of the string with [[ and ]]. Note that the RegEx pattern matching the beginning of a line is ^. The RegEx pattern for matching the end of a line is $.

Expression:  replaceAll(coordinates,' ','],[')

Expression:  replaceAll(coordinates,'^','[[')

Expression:  replaceAll(coordinates,'$',']]')

Your GeoEvent Service so far looks like:

Capture.png

And is producing output which looks like:

Capture1.png

Now you need to complete the formatting of your coordinate string to create a string representation of a Geometry. For this step I chose to copy the GeoEvent Definition used by the PolygonCoordinatesFeed input and add a field named GeomString. A Field Maper processor maps the existing coordinates and trackid into the new event structure leaving GeomString unmapped. Another Field Calculator processor will write its result into this new field. I do this so that the Field Calculator can write to an existing field without having to create an event defintion on-the-fly in order to write to a new field.

Here is the expression used in this most recent Field Calculator processor:

'{"rings":[' + coordinates + '],"spatialReference":{"wkid":4326}}'

What I'm doing here is prepending a literal string {"rings":[ to the coordinates value and appending a literal string ],"spatialReference":{"wkid":4326}} to the end of the string.

A final Field Mapper takes the event structure with the string representation of the Geometry and maps it to a field named Geometry. I now have an event with a field named trackid and a field named Geometry which I can send to a stream service to display the Geometry I've computed from the coordinate values received from the original feed. Here's my final GeoEvent Service:

Capture2.png

I've attached an XML export of this configuration for both the 10.3.1 and 10.4 product releases. You will, of course, need to fix any validation errors by publishing your own stream service or switching to use a different output connector if you want to import this configuration.

Hope this information in helpful -

RJ