我是一名从事某些空域建模实验的业余飞行员。我想要实现的是一个轻松创建空域横截面的工具,即3D空域到2D。所以最后我希望有一个类似于这个创建的图像:airspace example。准确性并不重要,因为这些横截面不会用于导航目的,而只能用于培训/可视化。因此坐标几何就足够了,不需要测地线计算。
目前,我在我的数据库中存储GeoJSON 2D几何图形(所有多边形),其中包含每个空域元素的较低和较高海拔高度限制的附加元数据。因此,我实际上只在我的OpenLayers和Leaflet.js地图上显示2D数据。
我希望用户能够在地图上绘制线串(请参见下图中的绿色线串,为了演示目的,笔划宽度显着增加)。我可以使用OpenLayers或Leaflet。结果应该是与用户绘制的线相交的2D元素的一维横截面,就像我在这个艺术插图中一样:
澄清:如果输出的1维横截面的长度是例如1L,那么示例中的横截面的内容应该是以下几何的集合:1)0.1L和0.1L之间的黑线0.5L和2)0.7L和0.825L之间的红线。
用户界面部分是可行的,它将在OpenLayers或Leaflet之上运行。我还发现了各种语言的几种算法,用于确定两条线是否相交,甚至找出交点。我可以使用Raphael.js绘制横截面。
我应该能够在一两天内完成所有这些......但我想知道是否有更容易的路径?例如,有没有人知道一个能够计算我想要实现的横截面的软件库?哦,请不要提到10,000美元的GIS套餐: - )。
由于这将是一个Web应用程序,我主要研究Javascript,Perl或PHP解决方案。 GeoJSON Utilities for JavaScript看起来非常有希望计算交叉点,但我想知道是否还有其他交叉点?
答案 0 :(得分:0)
发布我自己的问题的答案以供将来参考。我能够提出一个创建空域横截面的解决方案。它基于坐标几何。
1)输入数据是横截面的起点和终点坐标。
2)遍历所有区域并检查起始和/或结束坐标是否落在任何空域区域(多边形)内。 PHP代码从另一个SO答案略微修改,以检查一个点是否在多边形内:
// Point class, storage of lat/long-pairs
class Point {
var $lat;
var $long;
function Point($lat, $long) {
$this->lat = $lat;
$this->long = $long;
}
}
function pointInPolygon($p, $polygon) {
$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)
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;
}
3)遍历包含空域数据的每个区域(多边形)的所有线段。从另一个SO答案略微修改的PHP代码返回两个线段的交叉点:
function Det2($x1, $x2, $y1, $y2) {
return ($x1 * $y2 - $y1 * $x2);
}
function lineIntersection ($v1Y, $v1X, $v2Y, $v2X, $v3Y, $v3X, $v4Y, $v4X) {
$tolerance = 0.000001;
$a = Det2($v1X - $v2X, $v1Y - $v2Y, $v3X - $v4X, $v3Y - $v4Y);
if (abs($a) < $tolerance) return null; // Lines are parallel
$d1 = Det2($v1X, $v1Y, $v2X, $v2Y);
$d2 = Det2($v3X, $v3Y, $v4X, $v4Y);
$x = Det2($d1, $v1X - $v2X, $d2, $v3X - $v4X) / $a;
$y = Det2($d1, $v1Y - $v2Y, $d2, $v3Y - $v4Y) / $a;
if ($x < min($v1X, $v2X) - $tolerance || $x > max($v1X, $v2X) + $tolerance) return null;
if ($y < min($v1Y, $v2Y) - $tolerance || $y > max($v1Y, $v2Y) + $tolerance) return null;
if ($x < min($v3X, $v4X) - $tolerance || $x > max($v3X, $v4X) + $tolerance) return null;
if ($y < min($v3Y, $v4Y) - $tolerance || $y > max($v3Y, $v4Y) + $tolerance) return null;
return array($x, $y);
}
4)如果存在交叉段,则从横截面的起始坐标计算出交叉点的距离(作为上一步的结果)。将其除以横截面的总长度,以获得横截面线上空域区域边界的相对位置。
5)根据第2点和第4点的结果,绘制SVG多边形。相对交叉点位置转换为多边形的X坐标,高度数据(下限和上限)成为多边形的Y坐标。