查找重叠方块的所有点

时间:2013-09-18 14:19:41

标签: php intersection contour

设置:

    一个。 2D表面
    湾点(带有x,y坐标),当连接成正方形时。
    ℃。我找到了一个算法,找到这些方块的交点,所以假设我们也有它们。

问题是:如何获得正方形轮廓的点。

我已经包含了一张图片以便更好地理解。

contour example

我正在调查http://en.wikipedia.org/wiki/Convex_hull_algorithms,但似乎他们都跳过了这些交叉点(90'角)。

我在php中写这个,但我甚至喜欢看到伪代码。

1 个答案:

答案 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);
*/

?>
相关问题