How to find multiple points within a polygon - php

I am using the following code to test if a point is in a polygon, however I would like to make it work for multipliable points, but when I run it though a loop it fails to run correctly.
Polygon array = (52.62806176021313, 1.0546875),(52.435920583590125, 0.82672119140625),(52.26479561297205, 0.78277587890625),(52.24966453484505, 1.0986328125),(52.37224556866933, 1.34857177734375),(52.63973017532399, 1.46392822265625),(52.73795463681313, 1.25518798828125)
I split it up before hand.
Without Loop
$Latx = 52.5; //Y Point to test if inside
$LonX = 1.1; //X Point to test if inside
$VTX = $LON; //X array of polygon
$VTY = $LAT; //Y array of polygon
$POINTS = count($VTX) - 1; //number of polygon sides
//=====================================================
if (is_in_polygon($POINTS, $VTX, $VTY, $LonX, $LatY)){
echo "Is in polygon ($LatY,$LonX)";
echo "<br>";
}
else {
echo "Is not in polygon ($LatY,$LonX)";
}
echo "<br>"
function is_in_polygon($POINTS, $VTX, $VTY, $LonX, $LatY)
{
$i = $j = $c = 0;
for ($i = 0, $j = $POINTS ; $i < $POINTS; $j = $i++) {
if ((($VTY[$i] > $LatY != ($VTY[$j] > $LatY)) &&
($LonX < ($VTX[$j] - $VTX[$i]) * ($LatY - $VTY[$i]) /
($VTY[$j] - $VTY[$i]) + $VTX[$i]) ) )
$c = !$c;
}
return $c;
}
Trying with a Loop
for ($x=0; $x<=1000; $x++) {
$QU="SELECT lat,lon FROM DBTable LIMIT $x,1";
$RT=mysql_query($QU,$db);
if (!$RT) {
die("Invalid query: " . mysql_error());
}
while ($row = mysql_fetch_assoc($RT)){
$LonX[$x]=$row["lat"];
$LatY[$x]=$row["lon"];
if (is_in_polygon($POINTS, $VTX, $VTY, $LonX[$x], $LatY{$x])){
echo "Is in polygon ($LatY[$x],$LonX[$x])";
echo "<br>";
}
else echo "Is not in polygon ($LatY[$x],$LonX[$x])";
echo "<br>"
}
}

Related

PHP - Location inside multiple polygons

How can i turn this in to supporting more polygons than just this one? I think of something with arrays but I’m lost this code works with one polygon but just can’t get any further this is what I got:
I would like it to check if the point is in polygon A or B or C and so on depending on how many polygons I got right now it only checking if point is inside polygon A.
class Point {
public $lat;
public $long;
function Point($lat, $long) {
$this->lat = $lat;
$this->long = $long;
}
}
//the Point in Polygon function
function pointInPolygon($p, $polygon) {
//if you operates with (hundred)thousands of points
set_time_limit(60);
$c = 0;
$p1 = $polygon[0];
$n = count($polygon);
for ($i=1; $i<=$n; $i++) {
$p2 = $polygon[$i % $n];
if ($p->long > min($p1->long, $p2->long)
&& $p->long <= max($p1->long, $p2->long)
&& $p->lat <= max($p1->lat, $p2->lat)
&& $p1->long != $p2->long) {
$xinters = ($p->long - $p1->long) * ($p2->lat - $p1->lat) / ($p2->long - $p1->long) + $p1->lat;
if ($p1->lat == $p2->lat || $p->lat <= $xinters) {
$c++;
}
}
$p1 = $p2;
}
// if the number of edges we passed through is even, then it's not in the poly.
return $c%2!=0;
}
$polygon = array(
new Point(54.992883, -9.860767),
new Point(54.992775, -9.860289),
new Point(54.992236,- 9.861030),
new Point(54.992473, -9.862007)
);

Can't understand why my php cosine similarity code isn't working

I'm working on a website for my friend's gaming clan. I'm trying to have a php code that takes the player's coordinates, loops over some known locations and print the name of the closest location.
I can't get it to work however. It always seems to want to print "Balota" which is index 1 in the array. I also noticed that the cosine function can't be working as all values are above 1.0.
But I'm completely stuck now. I think I've been beating my head over it for too long and its something right in front of me but I can't see it.
<?php
function DotProd($loc1,$loc2){
return array_sum(array_map(create_function('$a, $b', 'return $a * $b;'), $loc1, $loc2));
}
function CosineSim($loc1,$loc2){
return DotProd($loc2,$loc2)/sqrt(DotProd($loc1,$loc2)*DotProd($loc1,$loc2));
}
function Closest($loc){
$novo = array(11300,14300);
$balota = array(4500,2500);
$zelen = array(2500,5200);
$sever = array(7900,12600);
$vybor = array(4500,8200);
$nwaf = array(4500,10200);
$neaf = array(12100,12500);
$kamensk = array(7870,14600);
$bere = array(12900,10000);
$gorka = array(9600,8900);
$elektro = array(10100,2000);
$cherno = array(6600,2600);
$stary = array(6100,7700);
$novy = array(7000,7700);
$mysk = array(1100,7200);
$locations = array($novo,$balota,$zelen,$sever,$vybor,$nwaf,$neaf,
$kamensk,$bere,$gorka,$elektro,$cherno,$stary,$novy,$mysk);
$sim = 99999999999;
$locat = 0;
for($i = 14; $i >= 0; $i--){
$s = CosineSim($loc,$locations[$i]);
echo "<br>" . $i . " " . CosineSim($loc,$locations[$i]);
if($s < $sim){
$sim = $s;
$locat = $i;
}
}
$items = array("Novo","Balota","Zelenogorsk","Severograd","Vybor","NWAF","NEAF","Kamensk Military","Berezino",
"Gorka","Elektro","Cherno","Stary Sobor","Novy Sobor","Myshkino");
return $items[$locat];
}
$x = $_GET["xpos"];
$y = $_GET["ypos"];
$location = array($x,$y);
echo "<b>You are at " . $x . ":" . $y;
$index = Closest($location);
echo "<br>You're pretty close to ". $index . "<br>";
?>
I am using a distance calculation formula based on the link: https://www.mathwarehouse.com/algebra/distance_formula/index.php
I only changed CosineSim. The rest of the code remains the same. And you don't actually need DotProd. It's not elegant but it works for me.
function CosineSim($loc1,$loc2){
// sum of x coordinates
$x1 = ($loc1[0]-$loc2[0])*($loc1[0]-$loc2[0]);
// sum of y coordinates
$y2 = ($loc1[1]-$loc2[1])*($loc1[1]-$loc2[1]);
$summ = $x1 + $y2;
$sqrt_res = sqrt($summ);
return $sqrt_res;
}
If I enter something like:
You are at 4640:7205
...
You're pretty close to Vybor
Hope this helps!

PHP - Finding consecutive values in multidimensional associative arrays for seat reservation program

I'm working on a program to reserve seats for a show. I have a multidimensional array that is created using $row and $column variables. After making a few initial reservations, I need to pass integers into a function/some code to make further reservations.
I've tried looping through the array to find consecutive available seats (value "avail") but it ignores reserved seats or skips over them. I'll need to later use manhattan distance to reserve the best seats (from row 1, seat 6) first.
function to create the array:
//function to create seating chart data structure
function createChart($row, $column){
//create array for row values
$row_chart = array();
for($r=0; $r < $row; $r++){
$row_number = $r + 1;
$row_chart[$row_number] = array(); // array of cells for row $r
}
//create array for column values
$column_chart = array();
for($c=0; $c < $column; $c++){
$column_number = $c + 1;
//$location = $c_num;
$status = "avail";
foreach($row_chart as $key => $value){
$column_chart[$column_number] = $status; //add arrays of "seats" for each row
}
}
//nest the column array into the row array
foreach($row_chart as $key => $value){
foreach($column_chart as $k => $v){
$seating_chart[$key][$k] = $status;
}
}
//$seating_chart = array_combine($row_chart, $column_chart);
return $seating_chart;
}
function to make initial reservations:
$initial_reservation = "R1C4 R1C6 R2C3 R2C7 R3C9 R3C10";
$initial_reservation = explode(" ", $initial_reservation);
echo "<br> <br>";
print_r($initial_reservation);
$initial_res_length = count($initial_reservation);
echo "<br> <br>";
//echo $initial_res_length;
//split each seat up into integers to mark it reserved in the array
//issue for flexibility: find way to break up string by letters and numbers for larger charts
for($a = 0; $a < $initial_res_length; $a++){
$reso_row = substr($initial_reservation[$a], 1, 1);
//echo $reso_row . "<br>";
$reso_column = substr($initial_reservation[$a], 3, 2);
//echo $reso_column . "<br>";
$working_chart[$reso_row][$reso_column] = "reserved";
}
//echo "<br> <br>";
//echo "<pre>" . print_r($working_chart, 1) . "</pre>";
what I have so far in attempt to make further reservations:
//write some code to find consecutive seats
$seats_needed = 4;
$outer_array_length = count($working_chart);
//echo $outer_array_length;
for($d = 1; $d < $outer_array_length + 1; $d++){
for($e = 1; $e < $seats_needed + 1; $e++){
//issue: run through $seats_needed amount of times and executes the code block
//needed: check if $seats_needed amount of seats in available first then run reservation code
if($working_chart[$d][$e] === "avail"){
$working_chart[$d][$e] = "new reservation";
}
else{
echo "Sorry, not possible.";
}
}
break;
}
echo "<br> <br>";
echo "<pre>" . print_r($working_chart, 1) . "</pre>";
I'd like to be able to find a number of available seats ($seats_needed) first, and then loop through to reserve them.
I have initialized the $working_chart with :
$working_chart = createChart(10, 11);
I have written the attempt to make further reservations :
foreach(array_keys($working_chart) as $d ){
$maxColumn = count($working_chart[$d]) - $seats_needed + 1;
for($e = 1; $e <= $maxColumn ; $e++){
if(["avail"] === array_unique(array_slice($working_chart[$d], $e - 1 , $seats_needed))){
$working_chart[$d] = array_replace($working_chart[$d], array_fill($e, $seats_needed, "new reservation"));
break 2;
}
else{
echo "Sorry, not possible.";
}
}
}
I hope it can help you...

A 500 error has occurred - Executing long loop within PHP

A 500 error has occurred - executing long loop with PHP.
I am currently working on a scheduling system to schedule nurses on a hospital ward, I am using a genetic algorithm to carry this out.
so I randomly allocate each nurses to a shift.
and then work out how fit they are for the shift.
I then kill off any allocation which do not meet my fitness level.
I then randomly allocate a new timetable.
Assess that for fitness
kill off any allocation which do not meet my fitness level.
Merge the two timetables, keeping the fitness allocations
I loop through generating random timetable, accessing its fitness and merging the timetables
This works fine while looping through 30 - 100 times
Once I go past the 100 mark it sometimes fails - a 500 error has occurred
This always occurs when it takes over 2:30mins to complete the script
So I'm making the assumption at some point my server times out for taking too long?
I have added <?php set_time_limit(3600);
This is at the top of my file, not inside the constructor, or the class. Is it in the right place?
it still times out at 2 and a half minute,
Here is my code, the loop is the 200 loop
Still need to refractor my code so don't be too judgmental
<?php
set_time_limit(3600);
* Description of scheduler
*
* #author Dela
*/
include ("randomTtAllocation.php");
include ("fittness.php");
class scheduler {
private $randomTimetable;
private $timetable;
private $weight;
private $newTimetable ;
private $newWeight;
function __construct($labs,$students) {
echo "helloworld";
// create random timetable and print it
$r = new randomTtAllocation();
$this->randomTimetable = $r->__randomAllocation($labs, $students);
//echo "<br>" . " ............initial Time Table............." . "<br>" ;
echo "<br>";
echo "<br>";
echo "<br>";
$this->__printTt($this->randomTimetable, $this->randomTimetable);
// work out fittness for the timetable, return fit results and print
$fit = new fittness( $this->randomTimetable, $labs, $students , $r->__getNumOfSessions());
$this->newWeight = $fit->__getnewWeight();
$this->newTimetable = $fit->__getnewTimetable();;
//echo "<br>" . " ............newTimetable.........newWeight...." . "<br>" ;
//$this->__printTt($this->newTimetable, $this->newWeight );
// sort
$this->__sortTtByWeight();
$this->timetable = $this->newTimetable;
$this->weight = $this->newWeight;
for ($i = 0; $i < 200; $i++) {
// create second time table
$this->randomTimetable = $r->__randomAllocation($labs, $students);
// echo "<br>" . " ............initial Time Table............." . "<br>" ;
// $this->__printTt($this->randomTimetable, $this->randomTimetable);
// work out fittness for the timetable, return fit results and print
$fit = new fittness( $this->randomTimetable, $labs, $students , $r->__getNumOfSessions());
$this->newWeight = $fit->__getnewWeight();
$this->newTimetable = $fit->__getnewTimetable();
//echo "<br>" . " ............tempTimetable.........tempWeight...." . "<br>" ;
//$this->__printTt($this->newTimetable, $this->timetable );
$this->__sortTtByWeight();
// merge timetables
echo "<br>" . " ......old...........new." . "<br>" ;
$this->__printTt($this->timetable,$this->newTimetable );
$this->__mergeTimetables($this->newTimetable, $this->newWeight );
//echo "<br>" . " ........... mergedTimetable.........newWeight...." . "<br>" ;
//$this->__printTt($this->timetable,$this->weight );
// fittness of new timetable
$fit = new fittness( $this->timetable, $labs, $students , $r->__getNumOfSessions());
echo "<br>" . " ......merged.......kulled" . "<br>" ;
$this->__printTt($this->timetable,$fit->__getnewTimetable() );
$this->weight = $fit->__getnewWeight();
$this->timetable = $fit->__getnewTimetable();
$c[$i] = $this->__countSlotsAllocated();
echo "<br> ". $i;
}
print_r($c);
}
// sorts the re allocated time table by weight
function __sortTtByWeight() {
// for each slot
foreach($this->newTimetable as $l => $i_value) {
$size = 0;
// see how many sessions they are taking
while ($this->newTimetable[$l][$size] != "null") {
if ($this->newTimetable[$l][$size] == "0") {
break;
}
$size++;
}
for ($i = 1; $i < $size; $i++) {
$key = $this->newWeight[$l][$i];
$key1 = $this->newTimetable[$l][$i];
$k = $i - 1;
while ($k >= 0 && $this->newWeight[$l][$k] < $key) {
$this->newWeight[$l][$k + 1] = $this->newWeight[$l][$k];
$this->newTimetable[$l][$k + 1] = $this->newTimetable[$l][$k];
$k--;
}
$this->newTimetable[$l][$k + 1] = $key1;
$this->newWeight[$l][$k + 1] = $key;
}
}
}
function __countSlotsAllocated() {
$count = 0;
foreach($this->timetable as $i => $x_value) {
$j = 0;
while (($this->timetable[$i][$j] != "null") && ($this->timetable[$i][$j] != "0")){
$count++;
$j++;
}
}
echo "count " . $count;
return $count;
}
function __mergeTimetables($tempTimeTable,$tempWeight) {
// for each session
foreach($this->newTimetable as $i => $i_value) {
$j = 0;
$k = 0;
// while there are still students
while (($tempTimeTable[$i][$j] != "null") && ($tempTimeTable[$i][$j] != "0")) {
//echo $tempTimeTable[$i][$j];
// System.out.println(timeTable[i][k]);
// see if there is a free gap
while ($this->timetable[$i][$k] != "null") {
// if student is already taking that session
if ($tempTimeTable[$i][$j] == $this->timetable[$i][$k]) {
break;
}
if ($this->timetable[$i][$k] == "0") {
$this->timetable[$i][$k] = $tempTimeTable[$i][$j];
$this->weight[$i][$k] = $tempWeight[$i][$j];
break;
}
$k++;
}
if ($this->timetable[$i][$k] == "null") {
if ($tempWeight[$i][$j] < $this->weight[$i][0]) {
$this->timetable[$i][0] = $tempTimeTable[$i][$j];
$this->weight[$i][0] = $tempWeight[$i][$j];
}
}
$j++;
}
}
}
function __returnTimetable() {
return $this->timetable;
}
function __printTt($timetable, $weight) {
foreach($timetable as $x => $x_value) {
for ($i = 0; $i < 5; $i++) {
echo $timetable[$x][$i] . " ";
}
echo " . . . . .";
for ($i = 0; $i < 5; $i++) {
echo $weight[$x][$i] . " ";
}
echo "<br>";
}
}
}
Normally you shouldn't do all this work within the http request. Instead you should start a background task and have the web page show progress on the job.
The php configuration has a time limit per request which you can adjust, but it's not expected by users to take so long.

Optimized Logic to find high score

Basically this is related to a squash application where we have 2 scores. One is from winner point of view and another from loser point of view.
eg.
Score1: 11-5,11-5,11-5 (Winner point of view)
Score2: 5-11, 5-11,5-11 (Loser point of view)
Now in my logic i want to find which is the winner score and which is the loser score.
I have written my logic in the below way and it does work. But i want to know if their is any other better/optimized way of writing this.
$high1 = 0;
$high2 = 0;
$score1 = "2-11,5-11,4-11,4-4";
$score2 = "11-2,11-5,11-4,4-4";
$score1Array = explode(",",$score1);
$size = sizeof($score1Array);
for($i = 0; $i < $size; $i++) {
$checkscore1 = explode("-",$score1Array[$i]);
if($checkscore1[0] < $checkscore1[1]) {
$high1++;
}else if($checkscore1[0] > $checkscore1[1]) {
$high2++;
}
}
if($high1 > $high2) {
$winningScore = $score2;
$losingScore = $score1;
}else{
$winningScore = $score1;
$losingScore = $score2;
}
echo $winningscore;
echo $losingscore;
What about something like this:
function is_winning($score) {
$split_scores = preg_split('/(-|,)/', $score);
$wins = $losses = 0;
for($i = 0; $i < count($split_scores) / 2; $i += 2) {
if($split_scores[$i] > $split_scores[$i + 1])
$wins++;
if($split_scores[$i] < $split_scores[$i + 1])
$losses++;
}
return $wins > $losses;
}
Assuming $score is formatted as in your question. You can then use it like this:
$score1 = "2-11,5-11,4-11,4-4";
$score2 = "11-2,11-5,11-4,4-4";
if(is_winning($score1)) {
$winning_score = $score1;
$losing_score = $score2;
} else {
$winning_score = $score2;
$losing_score = $score1;
}
echo $winning_score;
echo $losing_score;
The idea is to split the score into an array where the even numbered indexes have the left score and the odd numbered indexes the right score. We then count the number of wins and the number of losses. If there's more wins then losses then we return true since the score was a winning score. If there's not more wins then losses we simply return false.
This should work
$score1 = "2-11,5-11,4-11,4-4";
$score2 = "11-2,11-5,11-4,4-4";
$l = $r = 0;
$score1_sets_arr = explode(',', $score1);
foreach ($score1_sets_arr as $set_score) {
$set_score_arr = explode('-', $set_score);
if ($set_score_arr[0] > $set_score_arr[1]) {
$l++;
} else {
$r++;
}
}
if ($l > $r) {
$winning_score = $score1;
$losing_score = $score2;
} else {
$winning_score = $score2;
$losing_score = $score1;
}
you can use this :
<?php
$high1 = 0;
$high2 = 0;
$score1 = "2-11,5-11,4-11,4-4";
$score2 = "11-2,11-5,11-4,4-4";
$explode = explode(",",$score1);
for($i=0;$i< sizeof($explode);$i++){
$explode2= explode("-", $explode[$i]);
if($explode2[0] <= $explode2[1]){
echo $explode2[0]."-";
echo $explode2[1]." ";
}
}
echo "<br />";
for($i=0;$i< sizeof($explode);$i++){
$explode2= explode("-", $explode[$i]);
if($explode2[1] >= $explode2[0]){
echo $explode2[1]."-";
echo $explode2[0]." ";
}
}
?>
for Winner point of view, all big score in left,otherwise in right. so u can just detect the first score.
$score1Array = explode(",",$score1);
$checkscore1 = explode("-",$score1Array[$i]);
if($checkscore1[0] < $checkscore1[1]) {
echo $score2;
echo $score1;
}else{
echo $score1;
echo $score2;
}
Fix: above code is wrong,try this:
$score1value = eval(str_replace(",","+",$score1));
$score2value = eval(str_replace(",","+",$score2));
if($score1value < $score2value) {
echo $score2;
echo $score1;
}else{
echo $score1;
echo $score2;
}

Categories