geoPHP point in polygon - php

i need some help, google makes me sad
I got polygon http://geojson.io/#id=gist:anonymous/069b8a955897723ca256&map=4/58.75/48.03
And it covering a lot.
And i got geoPHP library https://github.com/phayes/geoPHP
Which got methods contains, covers, coveredBy...
And everything is normal, except that point like 74.224074, 96.428248 is always false for methods contains,coveredBy,covers, etc for this polygon. But it must be true.
Please, tell me why. I got a headache.
OR
Tell me please, how check that the lat lng is inside polygon. I tested about 3 libraries in perl and php, making my own code, etc... But the right results i got only from google containsLocation in javascript. But i have to use it on server side, not in browser. If there any chance to use containsLocation in nodejs it would be very nice.
Thank you
A little code for geoPHP:
$a='JSON FROM LINK';
$b=geoPHP::load("POINT(74.224074 96.428248)","wkt");
$a=geoPHP::load($a, 'json');
$result=$a->contains($b);
var_dump($result);
And it will be false
EDIT:
I think i got it.
GeoJson making coordinates in wrong way, longtitude, latitude. But it must be latitude, longtitude.
Will try and then write here if it works
ANSWER:
Use this www.birdtheme.org/useful/v3tool.html to make polygon on maps. It making it in right way(latitude,longtitude)
Working code for geoPHP:
include_once('geoPHP.inc');
$addr=file_get_contents('https://maps.googleapis.com/maps/api/geocode/json?address='.urlencode($_GET['address']).'&sensor=false');
foreach($addr->{results} as $addr1)
{
if(array_key_exists("geometry",$addr1)){
$lat=$addr1->{geometry}->{location}->{lat};
$lng=$addr1->{geometry}->{location}->{lng};
break;
}
}
$point1 = geoPHP::load("POINT($lat $lng)","wkt");
$ya200=geoPHP::load("POLYGON((41.51 12.3, 38.27 28.83, 32.55 41.84, 27.6 55.55, 29.54 71.37, 33.43 83.32, 36.6 94.92, 36.6 99.49, 35.17 111.45, 32.55 124.8, 35.17 130.78, 39.64 142.73, 43.58 152.58, 45.83 166.29, 56.17 163.83, 63.07 159.26, 68.66 154.69, 72.18 148.71, 75.93 140.63, 78.49 129.02, 80.3 114.26, 80.98 100.2, 81.2 87.54, 80.87 73.83, 79.62 59.41, 76.27 40.43, 71.07 28.13, 67.2 23.2, 63.55 20.04, 59.01 17.23, 54.16 15.12, 48.46 13.36,41.51 12.3))","wkt");
var_dump($ya200->contains($point1));

I am the maintainer of the geoPHP library (https://geophp.net). You have your latitude and longitude mixed up. WKT specifies that x comes first, then y, and then (optionally) z. This makes sense, as we usually do things in XYZ order.
It's conventional in mathematics for the horizontal axis to be X, and the vertical axis to be Y. If we think of a globe overlaid on a piece of graphing paper with X and Y axes specified, we can see that longitude is the horizontal axis, which corresponds to X, and the latitude is the vertical axis, which corresponds to Y. Therefore reading it as "longitude, latitude" makes perfect sense.
Regrettably, this sensical approach is backwards from the way mariners and other cartographers have described coordinates on the globe it throughout history. Historically it has often been described as "latitude, longitude".
This clash of history vs mathematical-convention is why you see different conventions in different systems. In Google Maps API its "latitude, longitude", while in OpenLayers it's "longitude, latitude".
In this particular case, you are using WKT, which is specified in "longitude, latitude" order.

WKT format expects POINT(lon, lat), with lon being first. You mixed up the order. Corrected:
geoPHP::load("POINT($lon $lat)","wkt");

I have answered almost the same question but don't know how to make a repost of it, so I just repeat it here (sorry)
If you use this PHP library (https://github.com/xopbatgh/sb-polygon-pointer), it may do all you need
(but first you need to convert GEOjson coordinates to lat/lng)
Plan to do:
Insert the coordinates of your polygon into array
Ask the library is the any point with lat/lng inside this polygon
$polygonBox = [
[55.761515, 37.600375],
[55.759428, 37.651156],
[55.737112, 37.649566],
[55.737649, 37.597301],
];
$sbPolygonEngine = new sbPolygonEngine($polygonBox);
$isCrosses = $sbPolygonEngine->isCrossesWith(55.746768, 37.625605);
// $isCrosses is boolean

After hours of struggle, I could not get the contains method to work with geoPHP. It turns out, as pointed out from this SO response that the geos library needs to be installed manually (no composer), which I could not get working after sifting through documentation on archive.org.
As an alternative, I found the mjaschen/phpgeo to be simple to use to do polygon contains point calculations. Simply load in your lat lons to objects and call the contains method as outlined in the documentation:
$polygon = new Polygon();
$polygon->addPoint(new Coordinate(12.3, 41.51));
$polygon->addPoint(new Coordinate(28.83, 38.27));
$polygon->addPoint(new Coordinate(41.84, 32.55));
$point = new Coordinate(74.224074, 96.428248)
var_dump($polygon->contains($point))

All advanced methods in geoPHP requires that GEOS is installed. If You are not able to install it but still want to use intersects test for point and polygon, then I have forked geoPHP and added Polygon->pointInPolygon and MultiPolygon->pointInPolygon methods for that purpose. Take a look:
https://github.com/sookoll/geoPHP
$point = \geoPHP::load('POINT (x y)','wkt');
$polygon = \geoPHP::load('POLYGON ((x y...))','wkt');
$point_is_in_polygon = $polygon->pointInPolygon($point);

Related

PChart - Y Axis does not start from 0

I generate stacked bar chart using PChart, but Y Axis does not start from 0.
Is there manual parameter that I should set? Here the chart
$graph->drawScale(array("Mode" => SCALE_MODE_START0));
This works for standard bar charts, I assume it would work for stacked. Give it a try.
There are actually a couple of ways to solve this issue. According to the documentation you should be able to use:
$graph->drawScale(array("Mode"=> SCALE_MODE_ADDALL_START0));
however, when I was generating stacked charts, it kept adding an additional mark at 110%, to solve this I decided to use:
$scaleProperties = array(0=>("Min"=>0, "Max"=>100));
$graph->drawScale(array("Mode" => SCALE_MODE_MANUAL, "ManualScale"=>$scaleProperties));
You would simply change the "Max" value to whatever your top end is, this forces the scale to stay between 0 and the maximum value.

Translating degrees to SVG coordinates

I am looking for a function either PHP or jQuery to translate degrees into SVG equivalent coordinates, if any, to ease up the conversions.
E.g.:
90 degree = x1="0%" y1="0%" x2="100%" y2="0%"
180 = x1="0%" y1="0%" x2="0%" y2="100%"
etc.. this is the question. I am looking for a function that will handle any conversion of degree from 0 to 360 into SVG coordinates.
I am looking into http://keith-wood.name/svg.html, and several other pages so far, but no luck.
A simple "no" will be very helpful also, if you are sure there is no such function exists. At least I will have to cease searching for something that do not exists :)
Any hint or reference will be very much appreciated. Thanks.
UPDATE:
A homework reference: http://www.zahniser.net/~russell/computer/index.php?title=Angle%20and%20Coordinates
It is simple geometry. Have a look at the unit circle http://en.wikipedia.org/wiki/Unit_circle
First convert your degrees to radians with
radians = degrees * Pi / 180
x = cos(radians) // will give you the value of y fom -1 to 1
y = sin(radians) // will give you the value of x fom -1 to 1
it's available in all programming languages I know, just choose the syntax that fits yours.
I'm assuming you're working with the <line> element. You could use the transform attribute to rotate the <line> by a specified degree. This is much simpler than calculating the values by hand.

Merging RGB channels back into a single image with ImageMagick (php)

So I have a situtation with ImageMagick and php where I need to processes each of the RGB channels separately and then merge them back together into the final image. So in the code I have below, $red, $green and $blue are the channels (as gray scale images). The following code is what I have tried (and a couple variations) but each time I end up with an image that only has Cyan, Magenta or Yellow showing through. In this case, the resulting image is Cyan.
$im->removeImage();
$im->addImage($red);
$im->addImage($green);
$im->addImage($blue);
$img = $im->combineImages(self::CHANNEL_ALL);
$im->removeImage();
$im->removeImage();
$im->removeImage();
$im->addImage($img);
I think part of my problem is that the PHP documentation doesn't say much about how to use combineImages and there are no samples so far as I can find. So it's very likely that I'm using that particular method incorrectly, and I suspect it has to do with how I am combining the images in the single Imagick object to begin with.
EDIT
This question ultimately boils down to this: How do I recreate the following script using only php?
convert tmp_r.png tmp_g.png tmp_b.png -combine tmp_rgb.png
[EDIT]
I have to admit, looking further into the documentation, Im not sure what the constant CHANNEL_ALL does. They do state that you can concatenate channels by logically ORing them together. You might try:
$im->combineImages(imagick::CHANNEL_RED | imagick::CHANNEL_GREEN | imagick::CHANNEL_BLUE);
[ORIGINAL]
I've been looking into this API, and honestly what I think you are looking for is the convert function, NOT the combine function.
Look At the below provided link and click specifically on "Combining RGB Channel Images"
http://www.imagemagick.org/Usage/color_basics/
Try that, leave a comment if you need further help :-)
So I think I've figured out how to get this to work. The missing piece was a call to flattenImages(). I'm not exactly sure why this worked, but it seems to be what I was looking for. Here's the code (keep in mind that $this is in the context of a member method of a class that extends Imagick):
$this->removeImage(); // gets rid of the old, unprocessed image
$rgb = clone $this;
$rgb->addImage($red);
$rgb->addImage($green);
$rgb->addImage($blue);
$rgb->flattenImages(); // this is what was missing above
$rgb = $rgb->combineImages(self::CHANNEL_ALL);
$this->addImage($rgb);
Can anyone comment on why this might be? I expected flattenImages() to merge the three images into one and destroy some of the information, but it appears that it actually tells ImageMagick to process all of the contained images together whereas it was processing them independently previously.
Try this:
$im->addImage($red);
$im->addImage($green);
$im->addImage($blue);
$im->combineImages(imagick::CHANNEL_RED | imagick::CHANNEL_GREEN | imagick::CHANNEL_BLUE);
btw combineImages doesn't return imagick object, but true/false indicating success or failure, so $im will contain your combined image.
Edit:
Apparently combineImages sucks big time, so here's an alternative: imagick::compositeImage
$im->compositeImage($red, imagick::COMPOSITE_COPY, 0, 0, imagick::CHANNEL_RED);
$im->compositeImage($green, imagick::COMPOSITE_COPY, 0, 0, imagick::CHANNEL_GREEN);
$im->compositeImage($blue, imagick::COMPOSITE_COPY, 0, 0, imagick::CHANNEL_BLUE);

How to convert torrent info hash for scrape?

I have a torrent hash from the magnet link. For example: fda164e7af470f83ea699a529845a9353cc26576
When I try to get information about leechers and peers I should request: http://tracker.publicbt.com/scrape?info_hash=???
How should I convert info hash for this request? Is it url encoding or becoding? how? In PHP.
It's a raw hexadecimal representation. Use pack() with H to convert it. Then URL encode it.
Got this python snippet from a colleague,
r = ''
s = 'fda164e7af470f83ea699a529845a9353cc26576'
for n in range(0, len(s), 2):
r += '%%%s' % s[n:n+2].upper()
print r
Output: %FD%A1%64%E7%AF%47%0F%83%EA%69%9A%52%98%45%A9%35%3C%C2%65%76
Works like a charm.
Edit: Works like a charm for getting the tracker to give back status 200 (ok) but still doesn't work for retrieving the torrent details...
In case someone is having trouble and comes across this thread in the future: the trick to this whole issue is to use the bool $raw_output argument of the PHP: sha1 function, setting it to "true".
The BDecode/DEncode classes can be found HERE. This project, called Trackon, also includes many other helpful classes to interact with torrent trackers and files.
So, in PHP, something like this will work to obtain the correct info hash for scraping the tracker for details:
include('./path/to/BDecode.php');
include('./path/to/BEncode.php');
function getHash($torFile){
$tfile = BDecode(file_get_contents($torFile));
$infohash = sha1(BEncode($tfile["info"]), TRUE);
return urlencode($infohash);
}
Then merely call it like so:
$hash = getHash('./path/to/.torrent');
Hope this helps someone out there. I was still scratching my head after reading many posts about how to obtain the correct info hash. I understand why this wasn't mentioned anywhere now though, this argument was added in PHP 5. If you're not running PHP 5, you will have to convert the sha1 hash to raw binary after you calculate it.

Projecting only some part of SVG on Google Map

I have SVG files, which I'd like to:
export and use as custom ground overlay with flat Euclidean projection (econym.org.uk/gmap/example_custommapflat.htm).
take only polygons and project them on Google Map
My SVG files have some rules in common:
they all are 4096x4096px
main objects of the map are centered
I have done some experiments, one of which could be seen here -- http://dev.ondigital.eu/map/map.php* (remove map.php from the URL to see svg, png and other files). As you can see, the problem is, that polygons points are being projected on the left side instead of being centered + the aspect ratio is absolutely incorrect.
So the question is: How to calculate the aspect ratio, when:
svg's viewBox attribute is present
svg's viewBox attribute is not present and/or each polygon has to be transformed (like in our map.svg).
And what about the offset (object centration)?
Thank you in advance!
*Not tested with IE
Is it possible that you're confusing DivPixels with ContainerPixels?
Try changing
var latlng = self.projection.fromPixelToLatLng(
new GPoint(point[0], point[1]),
self.map.getZoom()
);
to
var latlng = self.map.fromContainerPixelToLatLng(
new GPoint(parseFloat(point[0]), parseFloat(point[1]))
);
In this case, the fact that you use Strings rather than Numbers probably isn't causing any problems, yet, but it's a good idea to use Numbers now, and avoid the possibility of the + operator doing String concatenation instead of addition on your coordinates later in your project.

Categories