设置:
问题是:如何获得正方形轮廓的点。
我已经包含了一张图片以便更好地理解。
我正在调查http://en.wikipedia.org/wiki/Convex_hull_algorithms,但似乎他们都跳过了这些交叉点(90'角)。
我在php中写这个,但我甚至喜欢看到伪代码。
答案 0 :(得分:0)
<?php
//WARNING! we assume coords as non-polar. for this to work on large-scale, you need to convert polar into decard coords.
//Can be done outside this script.
//Points sample:
$points_raw=json_decode('{"1":[[41.014357690351,-73.73715475406],[41.029170309649,-73.73715475406],[41.014357690351,-73.75644124594],[41.029178309649,-73.73721675406],[41.014365690351,-73.75650324594],[41.031554690351,-73.73806375406],[41.046091309649,-73.78489424594],[41.014688690351,-73.78819424594],[41.012691690351,-73.75993275406],[41.012691690351,-73.77921924594],[41.015809690351,-73.75893475406],[41.053689309649,-73.76006575406],[41.053689309649,-73.77935224594],[41.050793309649,-73.78376624594],[41.043862309649,-73.79638424594],[41.029049690351,-73.79638424594],[41.019350690351,-73.79608224594],[41.033268690351,-73.73637875406],[41.048081309649,-73.73637875406],[41.048081309649,-73.75566524594],[41.014365690351,-73.75644124594],[41.029170309649,-73.73721675406],[41.018165690351,-73.75650324594],[41.029178309649,-73.74662775406],[41.031554690351,-73.74662775406],[41.033268690351,-73.73806375406],[41.043862309649,-73.78489424594],[41.019350690351,-73.78819424594],[41.015809690351,-73.75993275406],[41.014688690351,-73.77921924594],[41.018165690351,-73.75893475406],[41.047266309649,-73.76006575406],[41.050793309649,-73.77935224594],[41.046091309649,-73.78376624594],[41.029049690351,-73.79608224594],[41.047266309649,-73.75566524594]]}',1);
//BEGIN HERE:
$points=$points_raw[1];
function to_round($val)
{
//here we can try conversion from polar to decard. not sure if will work
//no conversion for now, but just rounding for comparsion
return round($val*1000000000000);
}
function sort_points_array($a, $b, $which)
{
$da=to_round($a[$which]);
$db=to_round($b[$which]);
if ($da == $db) {
return 0;
}
return ($da < $db) ? -1 : 1;
}
function sort_by_0($a, $b)
{
return sort_points_array($a, $b, 0);
}
function sort_by_1($a, $b)
{
return sort_points_array($a, $b, 1);
}
//BEGIN OF UNOPTIMIZED SORT
//sort by columns from left to right (does not have to be left/right on the map)
//but we will try :) 0 -> Y, 1 -> X
//sort by X, so lower X will be on top of array.
//and each point in those columns will be also sorted from top to bottom by their Y
usort($points,"sort_by_1");
//then foreach to split array by "columns";
$column_counter=0;
$point_columns=array();
$point_columns[$column_counter][]=$points[0];
foreach($points as $n_point=>$p_coords)
{
if($n_point>0)
{
if(to_round($p_coords[1]) > to_round($point_columns[$column_counter][1][1]))
$column_counter++;
$point_columns[$column_counter][]=$p_coords;
}
}
//now sort each column
$sorted_point_columns=array();
foreach($point_columns as $pcn => $p_column)
{
usort($p_column,"sort_by_0");
$sorted_point_columns[$pcn]=$p_column;
}
//SAME TO MAKE sorted_point_rows
usort($points,"sort_by_0");
$row_counter=0;
$point_rows=array();
$point_rows[$row_counter][]=$points[0];
foreach($points as $n_point=>$p_coords)
{
if($n_point>0)
{
if(to_round($p_coords[0]) > to_round($point_rows[$row_counter][0][0]))
$row_counter++;
$point_rows[$row_counter][]=$p_coords;
}
}
$sorted_point_rows=array();
foreach($point_rows as $prn => $p_row)
{
usort($p_row,"sort_by_1");
$sorted_point_rows[$prn]=$p_row;
}
// END OF UNOPTIMIZED SORT
//output array
$final_points_poly=array();
//clearly first point will be from 1st row;
//and we will go to the RIGHT in current row to find next point
$final_points_poly[0]=$sorted_point_rows[0][0];
//and let the magic begin:
$finished=false;
$last_point_index=0;
$points_total=count($points);
$pos_x=0; //pos by columns
$pos_y=0; //pos by rows
$relative_X=0; //relative X position in current ROW;
$relative_Y=0; //relative Y position in current COLUMN;
$rule=1; // right / down = 1, left / up = -1
//detect if we go by X or Y
$going_Y=false;
$finished=false;
while(!$finished)
{
if($going_Y)
{
$relative_Y+=$rule;
$last_point_index+=1;
$cur_p=$sorted_point_columns[$pos_x][$relative_Y];
$final_points_poly[$last_point_index]=$cur_p;
$going_Y = !$going_Y;
//search for pos_y:
foreach($sorted_point_rows as $cur_y => $row)
{
if(to_round($row[0][0]) == to_round($cur_p[0]))
{
$pos_y=$cur_y;
//search for relative_X
foreach($row as $cur_rel_x => $check_point)
{
if(to_round($check_point[1]) == to_round($cur_p[1]))
{
$relative_X=$cur_rel_x;
$rule = ($relative_X % 2 == 0 ? 1 : -1);
break 2;
}
//error_check 1
if($cur_rel_x == count($row)-1)
echo "error with calculating relative_X! check your data!\n";
}
}
//error_check 2
if($cur_y == count($sorted_point_rows)-1)
echo "error with calculating pos_y! check your data!\n";
}
}
else
{
$relative_X+=$rule;
$last_point_index+=1;
$cur_p=$sorted_point_rows[$pos_y][$relative_X];
$final_points_poly[$last_point_index]=$cur_p;
$going_Y = !$going_Y;
//search for pos_x:
foreach($sorted_point_columns as $cur_x => $column)
{
if(to_round($column[0][1]) == to_round($cur_p[1]))
{
$pos_x=$cur_x;
//search for relative_Y
foreach($column as $cur_rel_y => $check_point)
{
if(to_round($check_point[0]) == to_round($cur_p[0]))
{
$relative_Y=$cur_rel_y;
$rule = ($relative_Y % 2 == 0 ? 1 : -1);
break 2;
}
//error_check 1
if($cur_rel_y == count($column)-1)
echo "error with calculating relative_Y! check your data!\n";
}
}
//error_check 2
if($cur_x == count($sorted_point_columns)-1)
echo "error with calculating pos_x! check your data!\n";
}
}
if($last_point_index == $points_total-1)
{
$finished=true;
}
}
echo "all points:\n";
print_r($final_points_poly);
/*
//generate markers for google mapping
$out = "var bbs=[];var markers=[];";
$out .= "var pinI = new google.maps.MarkerImage('http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|ADDE63');";
$out .= "var pinI2 = new google.maps.MarkerImage('http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|FF8C00');";
$out .= "var pinI3 = new google.maps.MarkerImage('http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|990099');";
$out .= "bbs.push(new google.maps.Polyline({ ";
$out .= "path: [";
foreach($final_points_poly as $m){
$out .= "new google.maps.LatLng(".join(",",$m)."),";
}
$out .= "],";
$out .= "strokeColor: 'black', strokeOpacity: 0.4, strokeWeight: 1 }));";
$f = fopen("bbs.js",'w');
fwrite($f,$out);
fclose($f);
*/
?>