Select to view content in your preferred language

Verify if XY is inside polygon

11509
40
Jump to solution
02-06-2017 01:23 PM
jaykapalczynski
Honored Contributor

Is there a way via JS or Python to simply pass an XY to a function and determine if inside or outside a polygon (from a map Service)

I need to do this for Decimal Degrees, DMS, UTM etc.

I can do it like below BUT I would have to list out EVERY node and trying to do this for a complete state

function inside(point, vs) {
    var x = point[0], y = point[1];

    var inside = false;
    for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
        var xi = vs[i][0], yi = vs[i][1];
        var xj = vs[j][0], yj = vs[j][1];

        var intersect = ((yi > y) != (yj > y))
            && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
        if (intersect) inside = !inside;
    }

    return inside;
};

var polygon = [[4040958.21,261090.239],[4399737.773,261090.239],  [4399737.773,1004118.285],[4040958.21,1004118.285]]                                                 

<!--// The below are two examples.  One of them is inside the other is outside to bounding box
// inside -->
test = inside([ 4147263, 646445.066 ], polygon); // true
<!-- // outside -->
<!--
test = inside([ 4537048, 694061 ], polygon); // false
 -->
alert(test);
40 Replies
jaykapalczynski
Honored Contributor

I tried right in the Geometry Service and got this

0 Kudos
jaykapalczynski
Honored Contributor

I added [ ] in the geometry service and it worked....so looks like the string I am passing it...trying to add [ ] now

Nope...tried this and still no go

var XValue2 = document.getElementsByName('XCoord')[0].value
var YValue2 = document.getElementsByName('YCoord')[0].value
var GPSPoint = "[" + XValue2 + "," + YValue2 + "]"
var params = {
conversionType: "DMS",
sr: new SpatialReference({ wkid:4326}),
strings: [GPSPoint]
};
geometryService.fromGeoCoordinateString(params, function(result){
alert(result.coordinates);
}, function(error){
alert(error);
});

0 Kudos
jaykapalczynski
Honored Contributor

I tried to create an array from the string and got the below error:

Entering Coordinates into input boxes as such:  

76 0 51.2

36 25 47.25

error:

Error: Unable to complete operation

var XValue2 = document.getElementsByName('XCoord')[0].value
 //alert(XValue2);
 var YValue2 = document.getElementsByName('YCoord')[0].value 
 var GPSPoint = XValue2 + "," + YValue2
 var temp = new Array();
 temp = GPSPoint.split(",");
 alert(temp);
 
 var params = {
 conversionType: "DMS",
 sr: new SpatialReference({ wkid:4326}),
 strings: [temp]
 };
 geometryService.fromGeoCoordinateString(params, function(result){
 alert(result.coordinates);
 }, function(error){
 alert(error);
 });
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
jaykapalczynski
Honored Contributor

I really want to get this working and use the geometry service...I am stumped...

Int he mean time I just did this manually...converting the DMS and DDM coordinates manually and then pushing them into the Polygon.Contains 

Obviously I have some error trapping to do but that will come...

If you have any more ideas why I am getting errors with your example please let me know.

          }else if(document.getElementById('DMS').checked) {
                  var [a, b, c] = XValue.split(' ');
                  var DegreeX = Number(a);
                  var MinuteX = Number(b);
                  var SecondX = Number(c);
                  var XValue = DegreeX + MinuteX/60 + SecondX/3600
                  
                  var [d, e, f] = YValue.split(' ');
                  var DegreeY = Number(d);
                  var MinuteY = Number(e);
                  var SecondY = Number(f);
                  var YValue = DegreeY + MinuteY/60 + SecondY/3600
                  
                  //alert(XValue + " " + YValue);
                  var DMSX = XValue
                  var DMSY = YValue
                  
                  var TextBoxpnt = new Point((DMSX), (DMSY));
          }else if(document.getElementById('DDM').checked) {        
                  var [a, b] = XValue.split(' ');
                  var DegreeX = Number(a);
                  var MinuteX = Number(b);
                  var XValue = MinuteX/60 + DegreeX
                  
                  var [d, e] = YValue.split(' ');
                  var DegreeY = Number(d);
                  var MinuteY = Number(e);
                  var YValue = MinuteY/60 + DegreeY
                  
                  //alert(XValue + " " + YValue);
                  var DDMX = XValue
                  var DDMY = YValue
                  var TextBoxpnt = new Point((DDMX), (DDMY));
          }     
0 Kudos
jaykapalczynski
Honored Contributor

Not sure how to mark this as "Mark Correct" as you have posted many things to a large issue.  I want to give you credit but also want to post the entire working code....not sure which one to mark as correct

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Jay,

  The reply that answer to original question would be most appropriate. Normally you should not keep tacking on more questions to the same thread, but start new post(s) for additional questions once the original has been answered.

0 Kudos
jaykapalczynski
Honored Contributor

Thanks for all your help....much appreciated...don't code for a while and you loose it....

Cheers

0 Kudos
RebeccaStrauch__GISP
MVP Emeritus

I agree with Robert that you need to mark the answer to the original question as the correct one, but make sure to mark those that were helpful as that too, since when others look at the thread in the future, that will be helpful to them.  If you don't ever get a definitive answer, you can always mark the helpfuls and then mark assumed answered (if you answer yourself, that is probably good protocol too).  In the future, if you start going way off the original question, probably better to branch the question or start a new. Again, makes it easier for others to find, vshaving it buried deep in the comments....my opinions.

jaykapalczynski
Honored Contributor

Thanks for ALL YOUR HELP ROBERT !!!!

OK this is what I have...

  • The user selects a Coordinate System
  • Based on this selection it chooses the correct output Spatial reference in the query to do the XY comparison
  • It then calls the getPoints function to compare the user XY against the geometry from the query using "polygon.contains"
  • In this case it simply updates some text in the webpage saying whether or not its inside the polygon

Any questions please ask

<!DOCTYPE html>
<html>
<head>
  <title>Verify XY Coordinates</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
  <link rel="stylesheet" href="http://js.arcgis.com/3.19/dijit/themes/claro/claro.css">
  <link rel="stylesheet" href="http://js.arcgis.com/3.19/esri/css/esri.css">
  
  <script src="http://js.arcgis.com/3.19/"></script>

  <script>
    require([
        "esri/map", "esri/geometry/Point", "dojo/ready", "dojo/parser", "esri/tasks/GeometryService", "esri/tasks/query", 
          "esri/SpatialReference", "esri/tasks/QueryTask", "dojo/dom", "dojo/on", "dojo/domReady!"], 
     function (
    Map, Point, ready, parser, GeometryService, Query, SpatialReference, QueryTask, dom, on) {
    
     ready(function(){          
     parser.parse();
     //ESRI Geometry Service
     var geometryService = new GeometryService("https://sampleserver5.arcgisonline.com/arcgis/rest/services/Utilities/Geometry/GeometryServer");

    function execute () {
          // DEFINE A NEW QUERY
          var query = new Query();
          var queryTask = new QueryTask("https://xxxx.gov/arcgis/rest/services/Public/Boundary/MapServer/0");
               
          if(document.getElementById('UTM17N').checked) {
            document.getElementById("p3").innerHTML = "UTM Zone 17N was selected";
               query.outSpatialReference = {wkid:26917}; 
          }else if(document.getElementById('UTM18N').checked) {
            document.getElementById("p3").innerHTML = "UTM Zone 18N was selected";
               query.outSpatialReference = {wkid:26918}; 
          }else if(document.getElementById('DD').checked) {
            document.getElementById("p3").innerHTML = "Decimal Degrees was selected";
               query.outSpatialReference = {wkid:4326}; 
          }
          // FINISH THE QUERY PARAMETERS AND CALL THE FUNCTION TO TEST
          query.where = "1=1";
          query.outFields = ["*"];
          query.returnGeometry = true;
          queryTask.execute(query, getPoints);
    }

     on(dom.byId("runQuery"), "click", execute);
     
     function getPoints(results) {
        var polygon = results.features[0].geometry;
        var XValue = document.getElementsByName('XCoord')[0].value
        var YValue = document.getElementsByName('YCoord')[0].value  
        var TextBoxpnt = new Point((XValue), (YValue));
        if (polygon.contains(TextBoxpnt)){
               document.getElementById("p2").innerHTML = (TextBox);               
          }else{
               document.getElementById("p2").innerHTML = (TextBox);
          }
     } 

     });
  });
  </script>

</head>
<body class="claro">
<form action="">
  <input type="radio" name="Coordinate" checked="checked" id="UTM17N" value="UTM17N"> UTM Zone 17N - (742833.345, 4176911.91)<br>
  <input type="radio" name="Coordinate" id="UTM18N" value="UTM18N"> UTM Zone 18N - (742833.345, 4176911.91)<br>
  <input type="radio" name="Coordinate" id="DD" value="DD"> Decimal Degrees - (-76.015778, 36.8631)<br>
</form>
  <p id="p3"></p>
  X Coordinate: <input id="XCoord" type="text" name="XCoord"><br>
  Y Coordinate: <input id="YCoord" type="text" name="YCoord"><br>
  <input type="button" value="Verify XY" id="runQuery" />
  <p id="p1">Click button to verify XY location in regards to VA Border</p>
  <p id="p2"></p>
</body>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Jay,

  OK, so if you want to allow the user to enter DMS or DDM then you will have to convert them to DD using the class I specified in my last reply.

0 Kudos