/    Sign up×
Community /Pin to ProfileBookmark

Can someone explain a few things to me?

Hi everyone, I’m not a JavaScript person, PHP I can get by with, JavaScript no. I’m trying to help out a friend with a point in polygon problem and the solution I have is in JavaScript but I’m trying to rewrite it in PHP and just need a few things to be explained if you don’t mind.

The script works as such, I give it the boundaries for a polygon, I click on the map and it tells me if I clicked inside or outside the polygon. I am trying to get it so I can give it several points and it just loops through the function and tells me if the various points are inside or outside the polygon.

Here is the script and I’ll tell you where I’m having problems:

<script type=”text/javascript”>
var map = null;
var polygon = null;

function GetMap() {
map = new VEMap(‘myMap’);
map.LoadMap();

//Plot Polygon
var points = new Array(
new VELatLong(41.7972300222736, -87.7281369157155),
new VELatLong(41.7983290222745, -87.7281489157156),
new VELatLong(41.798857022275, -87.7267849157143),
new VELatLong(41.7989060222752, -87.7266109157142),
new VELatLong(41.7990980222752, -87.7260359157136),
new VELatLong(41.7991840222754, -87.7258169157134),
new VELatLong(41.8001330222763, -87.7233909157112)
);

polygon = new VEShape(VEShapeType.Polygon, points);
polygon.HideIcon();
map.AddShape(polygon);
map.SetMapView(points);

//Add onclick handler
map.AttachEvent(“onclick”, map_click);
}

function map_click(eventArgs) {
var latlong = map.PixelToLatLong(new VEPixel(eventArgs.mapX, eventArgs.mapY));
alert(“Is Point Within Polyline:n” + GeoHelper.IsInPolygon(polygon.GetPoints(), latlong));
}

if (GeoHelper == undefined)
var GeoHelper = {};

GeoHelper.IsInPolygon=function(points,latlong) {
var i;
var j=points.length-1;
var inPoly=false;
var lat = latlong.Latitude;
var lon = latlong.Longitude;

for (i=0; i<points.length; i++) {
if (points.Longitude<lon && points[j].Longitude>=lon ¦¦ points[j].Longitude<lon && points.Longitude>=lon) {
if (points.Latitude+(lon-points.Longitude)/(points[j].Longitude-points.Longitude)*(points[j].Latitude-points.Latitude)<lat) {
inPoly=!inPoly;
}
}
j=i;
}

return inPoly;
};

</script>

In the IsInPolygon function, I know the var i is to start the loop but I don’t know what the var j is for. The [B]points.length-1[/B] is throwing me, I looked around and I think it’s a trim function, that it’s trying to eliminate any extra space from the end of the line, is that right? It confuses me because then in the if statements, I see the line:
[B]points.Longitude<lon && points[j].Longitude>=lon ¦¦ points[j].Longitude<lon && points.Longitude>=lon[/B]
And it’s the points[j].Longitude that again confuses me because of the [j], I’m not sure what that’s telling me.
And I don’t know what the j=i at the end of the for loop is for. They already returned the inPoly=!inPoly.

Sorry if I sound like an idiot, I realize it sounds a little stupid, I just have no idea what that means and I would like to get this finished and out of my head.

Thanks for any help you can give.

to post a comment
JavaScript

11 Comments(s)

Copy linkTweet thisAlerts:
@astupidnameDec 21.2008 — In the IsInPolygon function, I know the var i is to start the loop but I don't know what the var j is for. The points.length-1 is throwing me[/quote]

GeoHelper.IsInPolygon=function(points,latlong) {

var i;

var j=points.length-1; [/quote]


points.length-1 refers to the parameter (points) of the IsInPolygon function. The points parameter receives an array, and the variable j is set to be a number that is 1 less than the length of the array. Then j refers to the index number of the last item in the array.

It confuses me because then in the if statements, I see the line:

points.Longitude<lon && points[j].Longitude>=lon ¦¦ points[j].Longitude<lon && points.Longitude>=lon

And it's the points[j].Longitude that again confuses me because of the [j], I'm not sure what that's telling me.[/quote]


It looks to me as though the GeoHelper.IsInPolygon function takes two parameters: (points,latlong)

And from the code in the if statements it looks as though points is an array of objects which have Longitude and Latitude as their keys and numbers as their values, and could be defined as follows:

var somePoints = [

{ "Longitude":41.7972300222736 , "Latitude":-87.7281369157155 },

{ "Longitude":41.7983290222745 , "Latitude":-87.7281489157156 },

{ "Longitude":41.798857022275 , "Latitude":-87.7267849157143 }

];

And it looks to me as though the latlong parameter just takes a single object, also with Longitude and Latitude as it's keys, and numbers as it's values, and could be defined as follows:

var MYlatlong = { "Latitude":41.8001330222763 , "Longitude":-87.7233909157112 };

So it would appear you could maybe then feed the object array and the object to the GeoHelper.IsInPolygon function like so:

GeoHelper.IsInPolygon(somePoints,Mylatlong);

Or perhaps test it like so with an alert and see if it alerts false or not:

alert(GeoHelper.IsInPolygon(somePoints,Mylatlong));

although in the function they have this line: inPoly=!inPoly; -if both 'if' statements are true then inPoly=!inPoly where they could have just made it inPoly=true instead, I don't know why they made it !inPoly and I don't know if that will alert true or not, but should alert false if both 'if' statements are false, as inPoly is originally declared as false.

I don't understand either why they have: j=i; near the end of the for loop. Although, having said that, I just realized that is still inside the 'for' loop. And 'i' is not used anywhere else in the for loop apparently. So the first time through the for loop, the if statements are comparing the last item in the points array first (remember, initially j is equal to number equal to last array items index number), then j is set to the same value as i which is 0, and the loop continues until i reaches the same value as the length of the points array, each time incrementing j along with i. It does seem quite goofy, I don't know why it was important to check the last item first, instead of running straight through the array items in order using i only.

Well, that's about all I can tell you. Whether it makes sense or not... hope it helps!
Copy linkTweet thisAlerts:
@astupidnameDec 22.2008 — Actually, after looking at the usage of points inside the 'if' statments again, I am still confused about that myself, and believe while my description and examples are very close, I do not quite understand how they are getting from points.Longitude to points[indexnumber which is j].Longitude, as I don't see how points.Longitude is supposed to work without an index number.
Copy linkTweet thisAlerts:
@SandraG1952authorDec 22.2008 — If I add

var lat = 41.8002830222765;

var lon = -87.7233319157111;

into the IsInPolygon loop, the alert box returns true, no matter where I click. So I am guessing that if I can put my co-ordinates for the polygon into an array and run each point from the polygon against the lat and lon variables through the if statements and just have it echo if my point is in the polygon or not that it should work.

I am going to try it and let you know how I make out.
Copy linkTweet thisAlerts:
@mintedjoDec 22.2008 — I don't understand what the code does, but I suspect the reason it checks the last element and first element is to make a full polygon. Like doing a dot-to-dot. Start at the first dot and go all the way to the last dot. The first and last still won't be joined up. This is taken care of at the beginning in your algorithm.

I also suspect that where "points.Longitude" is used it should probably be points[i].Longitude because "points.Longitude" just makes no sense in that context.
Copy linkTweet thisAlerts:
@SandraG1952authorDec 23.2008 — I tried rewriting the code into php and, not surprisingly, it didn't work.

I am wondering, is the [B]var j=points.length-1;[/B] looping in reverse order or is it just getting the last value? I'm wondering this because the values for the polygon that I gave are just a small sample of the values (there can be more than 30 so I thought I would save space) and the last value is the same as the first.

The for loop is running through the polygon starting from the beginning so is it just checking each value against the last one?

Here is an example of values that I'm talking about:

var points = new Array(

new VELatLong(43.64486433588385, -79.3791389465332),

new VELatLong(43.64508171979899, -79.3930435180664),

new VELatLong(43.63682057801007, -79.38437461853027),

new VELatLong(43.63946054004705, -79.36819553375244),

new VELatLong(43.652720712083266, -79.37201499938965),

new VELatLong(43.65793702655821, -79.39111232757568),

new VELatLong(43.64927396999741, -79.37222957611084),

new VELatLong(43.64486433588385, -79.3791389465332)

);

I am going to keep trying but if someone can let me know what they think, I don't see the point in running through the loop twice, once from the beginning and once from the end, but I've seen weirder stuff that doesn't make sense to me.
Copy linkTweet thisAlerts:
@SandraG1952authorDec 23.2008 — Ok, in the time that it took for me to post that, I found the answer that it only gets the last value. I'm not sure what I was thinking but I am still working on it and will let you know how I make out.
Copy linkTweet thisAlerts:
@astupidnameDec 23.2008 — I am wondering, is the var j=points.length-1; looping in reverse order or is it just getting the last value?[/quote]

As I stated earlier:
So the first time through the for loop, the if statements are comparing the last item in the points array first (remember, initially j is equal to number equal to last array items index number), then j is set to the same value as i which is 0, and the loop continues until i reaches the same value as the length of the points array, each time incrementing j along with i.[/quote]

To clarify what I said there a little more...

It runs as many times as the number of items in the 'points' array, if 6 items loop runs 6 times.

For example if there are 6 items in the 'points' array of objects, the first time through the loop i is 0 and j is 5 (j = points.length-1 would be 5, which would be the index number of the last item in the array, as array indexes start at 0). The 'if' statements are evaluated, and if both are true then inPoly=!inPoly, then j is made equal to i at end of first (and every) cycle. Then the second cycle starts and i is incremented by one (i++), so in the beginning of the second cycle, i = 1 and j = 0 (0 because i had not been incremented yet when j was made equal to i at end of first cycle) and at end of second cycle j=i again.

Perhaps another way to show this in pseudo-code would be:

begin for loop{

cycle 1{

start:

i=0; j=5;

evaluate if's;

end:

i=0; j=0;

}

cycle 2{

start:

i=1; j=0;

evaluate if's;

end:

i=1; j=1;

}

cycle 3{

start:

i=2; j=1;

evaluate if's;

end:

i=2; j=2;

}

//continue cycling until i reaches 5 (assuming points.length = 6 items)

}

And again, as I was getting at earlier, and mintedjo pointed out more clearly here:
I also suspect that where "points.Longitude" is used it should probably be points[i].Longitude because "points.Longitude" just makes no sense in that context.[/quote]



I would add to that quote that it applies to "points.Latitude" also (those should probably be "points[i].Latitude" also, -assuming my earlier example of what I believe the 'points' array should look like is correct. I believe it is, but this could be dangerous!).
Copy linkTweet thisAlerts:
@SandraG1952authorDec 24.2008 — Ok, the mud is becoming a lot clearer.

So if I take this:

GeoHelper.IsInPolygon=function(points,latlong) {
var i;
var j=points.length-1;
var inPoly=false;
var lat = latlong.Latitude;
var lon = latlong.Longitude;

for (i=0; i<points.length; i++) {
if (points.Longitude<lon && points[j].Longitude>=lon ¦¦ points[j].Longitude<lon && points.Longitude>=lon) {
if (points.Latitude+(lon-points.Longitude)/(points[j].Longitude-points.Longitude)*(points[j].Latitude-points.Latitude)<lat) {
inPoly=!inPoly;
}
}
j=i;
}


It's telling me to declare a counter variable (i), a variable that will start at the end of the array (j), a variable that will eventually spit out whether the point is in the polygon or not (inPoly), and takes my latitude and longitude variables.

The loop starts i at 0 and to go no longer than the array size, incrementing each time through.

It should take the latitude and longitude of the first point in the array (which should be points[i].Longitude) and the longitude of the last point.



If both if statements are proven true, then inPoly will be true, will that stop the loop right there? I am guessing so, I mean if it's true at any point, why continue through the loop?



Lastly, so when j=i, j starts out as the last value in the array, then the first time j=i, j becomes the first value and i becomes the second and so on through the loop?



I am thinking since I'm trying to write this in PHP, I start my function and j would be something like $j = end($array); or $j = $array[5];



Again, I apologize if I sound a little silly, I appreciate everything! I am going to keep playing with this and will keep you posted.
Copy linkTweet thisAlerts:
@SandraG1952authorDec 26.2008 — Ok,

I think I got it working, however, I was wondering if someone could help me with just a, hopefully, simple thing.

In my PHP script, each time the two if statements looped through, instead of saving the result into a variable, I just had it echo True, if the statements failed, I had it echo False. I gave it a point I knew was inside the polygon and each time, it returned false with one exception where it returned true.

I was wondering what I can change in my javascript code to have it just use document.write() to say true or false instead of saving it into inPoly so that way I can compare the output of the two scripts. I tried changing it a bit but it's not writing the output. If someone can take a quick look, I would appreciate it:

Here is the original code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html>

<head>

<title></title>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

<script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.1"></script>

<script type="text/javascript">

var map = null;

var polygon = null;

function GetMap()
{
map = new VEMap('myMap');
map.LoadMap();

//Plot Polygon
var points = new Array(new VELatLong(29.9463460112365, -90.088701917914),

new VELatLong(29.9465700112368, -90.0891089179144),

new VELatLong(29.9468230112371, -90.0895389179148),

new VELatLong(29.9473330112376, -90.0904329179157),

new VELatLong(29.9527560112425, -90.1014569179259),

new VELatLong(29.9527350112426, -90.1014469179259),

new VELatLong(29.9527150112425, -90.1014379179259),

new VELatLong(29.9526910112425, -90.1014279179258),

new VELatLong(29.9516940112415, -90.1009789179255),

new VELatLong(29.9509780112409, -90.1006469179252));

polygon = new VEShape(VEShapeType.Polygon, points);
polygon.HideIcon();
map.AddShape(polygon);
map.SetMapView(points);

//Add onclick handler
map.AttachEvent("onclick", map_click);
}

function map_click(eventArgs)
{
var latlong = map.PixelToLatLong(new VEPixel(eventArgs.mapX, eventArgs.mapY));
alert("Is Point Within Polyline:n" + GeoHelper.IsInPolygon(polygon.GetPoints(), latlong));
}


if (GeoHelper == undefined)
var GeoHelper = {};

GeoHelper.IsInPolygon=function(points,latlong)
{
// This code adapted from the following URL:
// http://msdn.microsoft.com/en-us/library/cc451895.aspx

var i;
var j=points.length-1;
var inPoly=false;
var lat = 29.94943;
var lon = -90.09610;

for (i=0; i<points.length; i++)
{
if (points[i].Longitude<lon && points[j].Longitude>=lon || points[j].Longitude<lon && points[i].Longitude>=lon)
{
if (points[i].Latitude+(lon-points[i].Longitude)/(points[j].Longitude-points[i].Longitude)*(points[j].Latitude-points[i].Latitude)<lat)
{
inPoly=!inPoly;
}
}
j=i;
}

return inPoly;
};

</script>

</head>

<body onload="GetMap();">

<div id='myMap' style="position: relative; width: 600px; height: 400px;"></div>

</body>

</html>


And what I changed:

for (i=0; i<points.length; i++)

{

if (points[i].Longitude<lon && points[j].Longitude>=lon || points[j].Longitude<lon && points[i].Longitude>=lon)

{

if (points[i].Latitude+(lon-points[i].Longitude)/(points[j].Longitude-points[i].Longitude)*(points[j].Latitude-points[i].Latitude)<lat)

{

inPoly=!inPoly;

document.write("Is Point Within Polyline: Truen");

}

}

else {

document.write("Is Point Within Polyline: Falsen");

}



j=i;
}


I took out a few other things like the onClick event since that's not necessary if we're just printing text. Like I said, I really really appreciate any help anyone can give.

Thanks a lot and I hope you had a Merry Christmas!
Copy linkTweet thisAlerts:
@astupidnameDec 26.2008 — Since the script tag is in the head section, and that is where you are attempting the document.write, it will not show on the visible page. You could place an element such as a div or paragraph on your page and give it an id of "testDisplay" or whatever and then replace your document.write with document.getElementById("testDisplay").innerHTML = "your string here";

The other alternative (for testing), you could place the script tags in the body to see if the document.write works there.
Copy linkTweet thisAlerts:
@SandraG1952authorDec 26.2008 — Thanks, astupidname, I believe it is working properly.

In my PHP script, if both if statements are successful, I have it echo that the point is within the polygon and at what point in the loop it is true by showing the i value.

In the javascript file, if both statements are successful, I have it print that inPoly is true and at what loop through the for loop by calling the i value.

To make sure I just put the values of my points in the original script into the function at:

GeoHelper.IsInPolygon=function(points,latlong)
{

var i;
var j=points.length-1;
var inPoly=false;
var lat = 29.940425;
var lon = -90.072564;

for (i=0; i<points.length; i++)
{
if (points[i].Longitude<lon && points[j].Longitude>=lon || points[j].Longitude<lon && points[i].Longitude>=lon)
{
if (points[i].Latitude+(lon-points[i].Longitude)/(points[j].Longitude-points[i].Longitude)*(points[j].Latitude-points[i].Latitude)<lat)
{
inPoly=!inPoly;
}
}
j=i;
}

return inPoly;
};


and it always returns true.

I cannot thank you enough for helping me with this, I truly appreciate it. Thanks to mintedjo as well. You have let me go to bed early tonight! LOL
×

Success!

Help @SandraG1952 spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 5.19,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,

tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,
)...