Rewrite the line to polygon making routine to (hopefully) make the
line widths consistant and accurate always.
This commit is contained in:
parent
1a741df940
commit
e6c1dc4c0c
2 changed files with 123 additions and 68 deletions
|
@ -26,10 +26,11 @@ getIntersection (const Point3D &p0, const Point3D &p1,
|
||||||
((p3.y()-p2.y())*(p1.x()-p0.x()))-((p3.x()-p2.x())*(p1.y()-p0.y()));
|
((p3.y()-p2.y())*(p1.x()-p0.x()))-((p3.x()-p2.x())*(p1.y()-p0.y()));
|
||||||
|
|
||||||
if (u_den == 0) {
|
if (u_den == 0) {
|
||||||
if (u_num == 0)
|
if (u_num == 0) {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "Intersection: coincident lines");
|
SG_LOG(SG_GENERAL, SG_ALERT, "Intersection: coincident lines");
|
||||||
else
|
} else {
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "Intersection: parallel lines");
|
SG_LOG(SG_GENERAL, SG_ALERT, "Intersection: parallel lines");
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
double u = u_num/u_den;
|
double u = u_num/u_den;
|
||||||
|
@ -72,78 +73,128 @@ makePolygon (const Point3D &p, int width, TGPolygon &polygon)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Alternate makePolygon from a line routine
|
||||||
void
|
void
|
||||||
makePolygon (const Line &line, int width, TGPolygon &polygon)
|
makePolygon (const Line &line, int width, TGPolygon &polygon)
|
||||||
{
|
{
|
||||||
vector<TGPolygon> segment_list;
|
point_list left_side, right_side;
|
||||||
|
left_side.clear();
|
||||||
|
right_side.clear();
|
||||||
|
|
||||||
|
Point3D p0, p1, p2;
|
||||||
|
double a1, a2, dist;
|
||||||
|
double angle0, angle1;
|
||||||
|
double x, y, az1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// prime the pump
|
||||||
|
p0 = line.getPoint(0);
|
||||||
|
p1 = line.getPoint(1);
|
||||||
|
|
||||||
int nPoints = line.getPointCount();
|
// calculate heading of first line
|
||||||
int i;
|
geo_inverse_wgs_84(0, p0.y(), p0.x(), p1.y(), p1.x(),
|
||||||
for (i = 0; i < nPoints - 1; i++) {
|
&a1, &a2, &dist);
|
||||||
const Point3D p1 = line.getPoint(i);
|
angle0 = (a1 + a2) / 2.0;
|
||||||
const Point3D p2 = line.getPoint(i+1);
|
|
||||||
|
// calculate right offset edge for line
|
||||||
|
geo_direct_wgs_84(0, p0.y(), p0.x(),
|
||||||
|
CLAMP_ANGLE(angle0+90), width/2, &y, &x, &az1);
|
||||||
|
right_side.push_back( Point3D( x, y, 0 ) );
|
||||||
|
|
||||||
double angle1, angle2, dist, x, y, az;
|
// calculate left offset edge for line
|
||||||
|
geo_direct_wgs_84(0, p0.y(), p0.x(),
|
||||||
geo_inverse_wgs_84(0, p1.y(), p1.x(), p2.y(), p2.x(), &angle1, &angle2, &dist);
|
CLAMP_ANGLE(angle0-90), width/2, &y, &x, &az1);
|
||||||
|
left_side.push_back( Point3D( x, y, 0 ) );
|
||||||
|
|
||||||
|
int nPoints = line.getPointCount();
|
||||||
|
for ( i = 0; i < nPoints - 2; i++ ) {
|
||||||
|
p0 = line.getPoint(i);
|
||||||
|
p1 = line.getPoint(i+1);
|
||||||
|
p2 = line.getPoint(i+2);
|
||||||
|
|
||||||
|
// calculate heading of line0
|
||||||
|
geo_inverse_wgs_84(0, p0.y(), p0.x(), p1.y(), p1.x(),
|
||||||
|
&a1, &a2, &dist);
|
||||||
|
angle0 = (a1 + a2) / 2.0;
|
||||||
|
|
||||||
|
// calculate heading of line1
|
||||||
|
geo_inverse_wgs_84(0, p1.y(), p1.x(), p2.y(), p2.x(),
|
||||||
|
&a1, &a2, &dist);
|
||||||
|
angle1 = (a1 + a2) / 2.0;
|
||||||
|
|
||||||
|
// calculate right offset edge for line0
|
||||||
|
geo_direct_wgs_84(0, p0.y(), p0.x(),
|
||||||
|
CLAMP_ANGLE(angle0+90), width/2, &y, &x, &az1);
|
||||||
|
Point3D roff0( x, y, 0 );
|
||||||
|
geo_direct_wgs_84(0, p1.y(), p1.x(),
|
||||||
|
CLAMP_ANGLE(angle0+90), width/2, &y, &x, &az1);
|
||||||
|
Point3D roff1( x, y, 0 );
|
||||||
|
|
||||||
|
// calculate left offset edge for line0
|
||||||
|
geo_direct_wgs_84(0, p0.y(), p0.x(),
|
||||||
|
CLAMP_ANGLE(angle0-90), width/2, &y, &x, &az1);
|
||||||
|
Point3D loff0( x, y, 0 );
|
||||||
|
geo_direct_wgs_84(0, p1.y(), p1.x(),
|
||||||
|
CLAMP_ANGLE(angle0-90), width/2, &y, &x, &az1);
|
||||||
|
Point3D loff1( x, y, 0 );
|
||||||
|
|
||||||
|
// calculate right offset edge for line1
|
||||||
|
geo_direct_wgs_84(0, p1.y(), p1.x(),
|
||||||
|
CLAMP_ANGLE(angle1+90), width/2, &y, &x, &az1);
|
||||||
|
Point3D roff2( x, y, 0 );
|
||||||
|
geo_direct_wgs_84(0, p2.y(), p2.x(),
|
||||||
|
CLAMP_ANGLE(angle1+90), width/2, &y, &x, &az1);
|
||||||
|
Point3D roff3( x, y, 0 );
|
||||||
|
|
||||||
|
// calculate left offset edge for line1
|
||||||
|
geo_direct_wgs_84(0, p1.y(), p1.x(),
|
||||||
|
CLAMP_ANGLE(angle1-90), width/2, &y, &x, &az1);
|
||||||
|
Point3D loff2( x, y, 0 );
|
||||||
|
geo_direct_wgs_84(0, p2.y(), p2.x(),
|
||||||
|
CLAMP_ANGLE(angle1-90), width/2, &y, &x, &az1);
|
||||||
|
Point3D loff3( x, y, 0 );
|
||||||
|
|
||||||
|
// calculate intersection of roffset line1 and right offset line2
|
||||||
|
Point3D rint, lint;
|
||||||
|
if ( !getIntersection( roff0, roff1, roff2, roff3, rint ) ) {
|
||||||
|
// intersection failed, use the average of roff1 and roff2
|
||||||
|
rint = ( roff1 + roff2 ) / 2.0;
|
||||||
|
}
|
||||||
|
right_side.push_back( rint );
|
||||||
|
if ( !getIntersection( loff0, loff1, loff2, loff3, lint ) ) {
|
||||||
|
// intersection failed, use the average of roff1 and roff2
|
||||||
|
lint = ( loff1 + loff2 ) / 2.0;
|
||||||
|
}
|
||||||
|
left_side.push_back( lint );
|
||||||
|
}
|
||||||
|
|
||||||
|
// finish the end of the polyline
|
||||||
|
p0 = line.getPoint(nPoints - 2);
|
||||||
|
p1 = line.getPoint(nPoints - 1);
|
||||||
|
|
||||||
|
// calculate heading of last line
|
||||||
|
geo_inverse_wgs_84(0, p0.y(), p0.x(), p1.y(), p1.x(),
|
||||||
|
&a1, &a2, &dist);
|
||||||
|
angle0 = (a1 + a2) / 2.0;
|
||||||
|
|
||||||
|
// calculate right offset edge for line
|
||||||
|
geo_direct_wgs_84(0, p1.y(), p1.x(),
|
||||||
|
CLAMP_ANGLE(angle0+90), width/2, &y, &x, &az1);
|
||||||
|
right_side.push_back( Point3D(x, y, 0) );
|
||||||
|
|
||||||
|
// calculate left offset edge for line
|
||||||
|
geo_direct_wgs_84(0, p1.y(), p1.x(),
|
||||||
|
CLAMP_ANGLE(angle0-90), width/2, &y, &x, &az1);
|
||||||
|
left_side.push_back( Point3D(x, y, 0) );
|
||||||
|
|
||||||
|
// Finally assemble the polygon with counter clockwise winding
|
||||||
polygon.erase();
|
polygon.erase();
|
||||||
|
for ( i = 0; i < (int)right_side.size(); ++i ) {
|
||||||
// Wind each rectangle counterclockwise
|
polygon.add_node( 0, right_side[i] );
|
||||||
|
}
|
||||||
// Corner 1
|
for ( i = left_side.size() - 1; i >= 0; --i ) {
|
||||||
geo_direct_wgs_84(0, p1.y(), p1.x(), CLAMP_ANGLE(angle1+90), width/2, &y, &x, &az);
|
polygon.add_node( 0, left_side[i] );
|
||||||
polygon.add_node(0, Point3D(x, y, 0));
|
}
|
||||||
|
|
||||||
// Corner 2
|
|
||||||
geo_direct_wgs_84(0, p2.y(), p2.x(), CLAMP_ANGLE(angle1+90), width/2, &y, &x, &az);
|
|
||||||
polygon.add_node(0, Point3D(x, y, 0));
|
|
||||||
|
|
||||||
// Corner 3
|
|
||||||
geo_direct_wgs_84(0, p2.y(), p2.x(), CLAMP_ANGLE(angle1-90), width/2, &y, &x, &az);
|
|
||||||
polygon.add_node(0, Point3D(x, y, 0));
|
|
||||||
|
|
||||||
// Corner 4
|
|
||||||
geo_direct_wgs_84(0, p1.y(), p1.x(), CLAMP_ANGLE(angle1-90), width/2, &y, &x, &az);
|
|
||||||
polygon.add_node(0, Point3D(x, y, 0));
|
|
||||||
|
|
||||||
// Save this rectangle
|
|
||||||
segment_list.push_back(polygon);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build one big polygon out of all the rectangles by intersecting
|
|
||||||
// the lines running through the bottom and top sides
|
|
||||||
|
|
||||||
polygon.erase();
|
|
||||||
|
|
||||||
// Connect the bottom part.
|
|
||||||
int nSegments = segment_list.size();
|
|
||||||
Point3D intersection;
|
|
||||||
polygon.add_node(0, segment_list[0].get_pt(0, 0));
|
|
||||||
for (i = 0; i < nSegments - 1; i++) {
|
|
||||||
if (getIntersection(segment_list[i].get_pt(0, 0),
|
|
||||||
segment_list[i].get_pt(0, 1),
|
|
||||||
segment_list[i+1].get_pt(0, 0),
|
|
||||||
segment_list[i+1].get_pt(0, 1),
|
|
||||||
intersection))
|
|
||||||
polygon.add_node(0, intersection);
|
|
||||||
else
|
|
||||||
polygon.add_node(0, segment_list[i].get_pt(0, 1));
|
|
||||||
}
|
|
||||||
polygon.add_node(0, segment_list[nSegments-1].get_pt(0, 1));
|
|
||||||
|
|
||||||
// Connect the top part
|
|
||||||
polygon.add_node(0, segment_list[nSegments-1].get_pt(0, 2));
|
|
||||||
for (i = nSegments - 1; i > 0; i--) {
|
|
||||||
if (getIntersection(segment_list[i].get_pt(0, 2),
|
|
||||||
segment_list[i].get_pt(0, 3),
|
|
||||||
segment_list[i-1].get_pt(0, 2),
|
|
||||||
segment_list[i-1].get_pt(0, 3),
|
|
||||||
intersection))
|
|
||||||
polygon.add_node(0, intersection);
|
|
||||||
else
|
|
||||||
polygon.add_node(0, segment_list[i].get_pt(0, 3));
|
|
||||||
}
|
|
||||||
polygon.add_node(0, segment_list[0].get_pt(0, 3));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,10 @@ void makePolygon (const Point3D &p, int width, TGPolygon &polygon);
|
||||||
* a single point at y=90 and y=-90. As a result, this function
|
* a single point at y=90 and y=-90. As a result, this function
|
||||||
* uses the WGS80 functions, rather than simple Pythagorean stuff.
|
* uses the WGS80 functions, rather than simple Pythagorean stuff.
|
||||||
*
|
*
|
||||||
|
* Update CLO 7 Mar 2003: Function rewritten to carefully preserve
|
||||||
|
* specifed polygon width through any kind of point to point angle
|
||||||
|
* change.
|
||||||
|
*
|
||||||
* @param line The multi-segment line inside the new polygon.
|
* @param line The multi-segment line inside the new polygon.
|
||||||
* @param width The width in standard units (meters for FlightGear).
|
* @param width The width in standard units (meters for FlightGear).
|
||||||
* @param polygon The object that will hold the new polygon.
|
* @param polygon The object that will hold the new polygon.
|
||||||
|
|
Loading…
Add table
Reference in a new issue