From 47b1b05ac74c4a545ce5550e6c911a8132cbd334 Mon Sep 17 00:00:00 2001 From: PSadrozinski Date: Wed, 21 Sep 2011 20:00:11 -0400 Subject: [PATCH] Checkpoint : Linear features build their own superpoly_list on Finish() with correct texture and heading for each quad. Still need to clip them against their own accum during build btg --- src/Airports/GenAirports850/airport.cxx | 293 +++++-- src/Airports/GenAirports850/airport.hxx | 8 + src/Airports/GenAirports850/closedpoly.cxx | 25 +- src/Airports/GenAirports850/closedpoly.hxx | 9 +- src/Airports/GenAirports850/linearfeature.cxx | 746 ++++++++---------- src/Airports/GenAirports850/linearfeature.hxx | 82 +- 6 files changed, 645 insertions(+), 518 deletions(-) diff --git a/src/Airports/GenAirports850/airport.cxx b/src/Airports/GenAirports850/airport.cxx index 7a65a789..19f14590 100644 --- a/src/Airports/GenAirports850/airport.cxx +++ b/src/Airports/GenAirports850/airport.cxx @@ -189,7 +189,6 @@ static point_list calc_elevations( TGAptSurface &surf, return result; } - // Determine node elevations of each node of a TGPolygon based on the // provided TGAptSurface. Offset is added to the final elevation static TGPolygon calc_elevations( TGAptSurface &surf, @@ -211,11 +210,24 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) { TGPolygon apt_base; TGPolygon apt_clearing; + TGPolygon accum; accum.erase(); + TGPolygon line_accum; + line_accum.erase(); + // runways superpoly_list rwy_polys; - texparams_list texparams; + texparams_list rwy_tps; + + // pavements + superpoly_list pvmt_polys; + texparams_list pvmt_tps; + + // linear features + superpoly_list line_polys; + texparams_list line_tps; + int i, j, k; char buf[120]; // For debugging output Point3D p; @@ -225,9 +237,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) int rwy_count = 0; // Find the average of all the runway long / lats - // TODO : Need runway object... - - + // TODO : Need runway object... for (i=0; iIsPrecision() ) { - runways[i]->BuildBtg( altitude, &rwy_polys, &texparams, &accum, &apt_base, &apt_clearing ); + runways[i]->BuildBtg( altitude, &rwy_polys, &rwy_tps, &accum, &apt_base, &apt_clearing ); } } - // Now generate pavements + // Now generate pavements, and gather the linear features and lights from them if (pavements.size()) { for ( i=0; iBuildBtg( altitude, &rwy_polys, &texparams, &accum, &apt_base, &apt_clearing ); + pavements[i]->BuildBtg( altitude, &pvmt_polys, &pvmt_tps, &accum, &apt_base, &apt_clearing ); + AddFeatures( pavements[i]->GetFeatures() ); } } else { SG_LOG(SG_GENERAL, SG_ALERT, "no pavements"); } - // wipe out the pavements to save memory pavements.clear(); // Then the linear features - for ( i=0; i< 1; i++ ) + if (features.size()) { - // not yet... + for ( i=0; iBuildBtg( altitude, &line_polys, &line_tps, &line_accum ); + } } + else + { + SG_LOG(SG_GENERAL, SG_ALERT, "no pavements"); + } + // wipe out the pavements to save memory + features.clear(); if ( apt_base.total_size() == 0 ) { @@ -294,59 +314,11 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) TGPolygon divided_base = tgPolygonSplitLongEdges( filled_base, 200.0 ); TGPolygon base_poly = tgPolygonDiff( divided_base, accum ); - // do this when generating the polys themselves... -#if 0 - for ( k = 0; k < (int)rwy_polys.size(); ++k ) - { - SG_LOG(SG_GENERAL, SG_DEBUG, "add nodes/remove dups section = " << k << " " << rwy_polys[k].get_material()); - TGPolygon poly = rwy_polys[k].get_poly(); - SG_LOG(SG_GENERAL, SG_DEBUG, "total size before = " << poly.total_size()); - for ( i = 0; i < poly.contours(); ++i ) - { - for ( j = 0; j < poly.contour_size(i); ++j ) - { - Point3D tmp = poly.get_pt(i, j); - snprintf(buf, 119, " %.7f %.7f %.7f\n", tmp.x(), tmp.y(), tmp.z() ); - SG_LOG(SG_GENERAL, SG_DEBUG, buf); - } - } - - poly = remove_dups( poly ); - SG_LOG(SG_GENERAL, SG_DEBUG, "total size after remove_dups() = " << poly.total_size()); - - for ( i = 0; i < poly.contours(); ++i ) - { - for ( j = 0; j < poly.contour_size(i); ++j ) - { - Point3D tmp = poly.get_pt(i, j); - snprintf(buf, 119, " %.7f %.7f %.7f\n", tmp.x(), tmp.y(), tmp.z() ); - SG_LOG(SG_GENERAL, SG_DEBUG, buf); - } - } - - poly = reduce_degeneracy( poly ); - SG_LOG(SG_GENERAL, SG_DEBUG, "total size after reduce_degeneracy() = " << poly.total_size()); - - for ( i = 0; i < poly.contours(); ++i ) - { - for ( j = 0; j < poly.contour_size(i); ++j ) - { - Point3D tmp = poly.get_pt(i, j); - snprintf(buf, 119, " %.7f %.7f %.7f\n", tmp.x(), tmp.y(), tmp.z() ); - SG_LOG(SG_GENERAL, SG_DEBUG, buf); - } - } - - rwy_polys[k].set_poly( poly ); - } - // END do this when generating polys -#endif - // add segments to polygons to remove any possible "T" // intersections TGTriNodes tmp_nodes; - // build temporary node list + // build temporary node list from runways... for ( k = 0; k < (int)rwy_polys.size(); ++k ) { TGPolygon poly = rwy_polys[k].get_poly(); @@ -358,6 +330,34 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) } } } + + // and pavements + for ( k = 0; k < (int)pvmt_polys.size(); ++k ) + { + TGPolygon poly = pvmt_polys[k].get_poly(); + for ( i = 0; i < poly.contours(); ++i ) + { + for ( j = 0; j < poly.contour_size( i ); ++j ) + { + tmp_nodes.unique_add( poly.get_pt(i, j) ); + } + } + } + + // and linear features + for ( k = 0; k < (int)line_polys.size(); ++k ) + { + TGPolygon poly = line_polys[k].get_poly(); + for ( i = 0; i < poly.contours(); ++i ) + { + for ( j = 0; j < poly.contour_size( i ); ++j ) + { + tmp_nodes.unique_add( poly.get_pt(i, j) ); + } + } + } + + // and the base for ( i = 0; i < base_poly.contours(); ++i ) { for ( j = 0; j < base_poly.contour_size( i ); ++j ) @@ -376,6 +376,7 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) } } + // second pass : runways for ( k = 0; k < (int)rwy_polys.size(); ++k ) { TGPolygon poly = rwy_polys[k].get_poly(); @@ -385,6 +386,27 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) rwy_polys[k].set_poly( poly ); } + // second pass : and pavements + for ( k = 0; k < (int)pvmt_polys.size(); ++k ) + { + TGPolygon poly = pvmt_polys[k].get_poly(); + poly = add_nodes_to_poly( poly, tmp_nodes ); + SG_LOG(SG_GENERAL, SG_DEBUG, "total size after add nodes = " << poly.total_size()); + + pvmt_polys[k].set_poly( poly ); + } + + // second pass : and lines + for ( k = 0; k < (int)line_polys.size(); ++k ) + { + TGPolygon poly = line_polys[k].get_poly(); + poly = add_nodes_to_poly( poly, tmp_nodes ); + SG_LOG(SG_GENERAL, SG_DEBUG, "total size after add nodes = " << poly.total_size()); + + line_polys[k].set_poly( poly ); + } + + // One more pass to try to get rid of other yukky stuff for ( k = 0; k < (int)rwy_polys.size(); ++k ) { @@ -402,6 +424,39 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) rwy_polys[k].set_poly( poly ); } + for ( k = 0; k < (int)pvmt_polys.size(); ++k ) + { + TGPolygon poly = pvmt_polys[k].get_poly(); + + SG_LOG(SG_GENERAL, SG_DEBUG, "total size of section " << k << " before =" << poly.total_size()); + + poly = remove_dups( poly ); + SG_LOG(SG_GENERAL, SG_DEBUG, "total size after remove_dups() = " << poly.total_size()); + poly = remove_bad_contours( poly ); + SG_LOG(SG_GENERAL, SG_DEBUG, "total size after remove_bad() = " << poly.total_size()); + poly = remove_tiny_contours( poly ); + SG_LOG(SG_GENERAL, SG_DEBUG, "total size after remove_tiny_contours() = " << poly.total_size()); + + pvmt_polys[k].set_poly( poly ); + } + + for ( k = 0; k < (int)line_polys.size(); ++k ) + { + TGPolygon poly = line_polys[k].get_poly(); + + SG_LOG(SG_GENERAL, SG_DEBUG, "total size of section " << k << " before =" << poly.total_size()); + + poly = remove_dups( poly ); + SG_LOG(SG_GENERAL, SG_DEBUG, "total size after remove_dups() = " << poly.total_size()); + poly = remove_bad_contours( poly ); + SG_LOG(SG_GENERAL, SG_DEBUG, "total size after remove_bad() = " << poly.total_size()); + poly = remove_tiny_contours( poly ); + SG_LOG(SG_GENERAL, SG_DEBUG, "total size after remove_tiny_contours() = " << poly.total_size()); + + line_polys[k].set_poly( poly ); + } + + SG_LOG(SG_GENERAL, SG_DEBUG, "add nodes base "); SG_LOG(SG_GENERAL, SG_DEBUG, " before: " << base_poly); SG_LOG(SG_GENERAL, SG_DEBUG, " tmp_nodes size = " << tmp_nodes.get_node_list().size()); @@ -430,20 +485,48 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) SG_LOG(SG_GENERAL, SG_DEBUG, "total size after = " << tri.total_size()); TGPolygon tc; - if ( rwy_polys[i].get_flag() == "taxi" ) - { - SG_LOG(SG_GENERAL, SG_DEBUG, "taxiway, no clip"); - tc = rwy_section_tex_coords( tri, texparams[i], false ); - } - else - { - tc = rwy_section_tex_coords( tri, texparams[i], true ); - } + tc = rwy_section_tex_coords( tri, rwy_tps[i], true ); rwy_polys[i].set_tris( tri ); rwy_polys[i].set_texcoords( tc ); } + // tesselate the polygons and prepair them for final output + for ( i = 0; i < (int)pvmt_polys.size(); ++i ) + { + SG_LOG(SG_GENERAL, SG_DEBUG, "Tesselating section = " << i << " flag = " << pvmt_polys[i].get_flag()); + + TGPolygon poly = pvmt_polys[i].get_poly(); + SG_LOG(SG_GENERAL, SG_DEBUG, "contours before " << poly.contours() << " total points before = " << poly.total_size()); + TGPolygon tri = polygon_tesselate_alt( poly ); + SG_LOG(SG_GENERAL, SG_DEBUG, "total size after = " << tri.total_size()); + + TGPolygon tc; + tc = rwy_section_tex_coords( tri, pvmt_tps[i], false ); + + pvmt_polys[i].set_tris( tri ); + pvmt_polys[i].set_texcoords( tc ); + pvmt_polys[i].set_tri_mode( GL_TRIANGLES ); + } + + // tesselate the polygons and prepair them for final output + for ( i = 0; i < (int)line_polys.size(); ++i ) + { + SG_LOG(SG_GENERAL, SG_DEBUG, "Tesselating section = " << i << " flag = " << pvmt_polys[i].get_flag()); + + TGPolygon poly = line_polys[i].get_poly(); + SG_LOG(SG_GENERAL, SG_DEBUG, "contours before " << poly.contours() << " total points before = " << poly.total_size()); + TGPolygon tri = polygon_tesselate_alt( poly ); + SG_LOG(SG_GENERAL, SG_DEBUG, "total size after = " << tri.total_size()); + + TGPolygon tc; + tc = rwy_section_tex_coords( tri, line_tps[i], false ); + + line_polys[i].set_tris( tri ); + line_polys[i].set_texcoords( tc ); + line_polys[i].set_tri_mode( GL_TRIANGLES ); + } + SG_LOG(SG_GENERAL, SG_DEBUG, "Tesselating base"); TGPolygon base_tris = polygon_tesselate_alt( base_poly ); @@ -534,6 +617,78 @@ void Airport::BuildBtg(const string& root, const string_list& elev_src ) } } + for ( k = 0; k < (int)pvmt_polys.size(); ++k ) + { + SG_LOG(SG_GENERAL, SG_DEBUG, "tri " << k); + // TGPolygon tri_poly = rwy_tris[k]; + TGPolygon tri_poly = pvmt_polys[k].get_tris(); + TGPolygon tri_txs = pvmt_polys[k].get_texcoords(); + string material = pvmt_polys[k].get_material(); + SG_LOG(SG_GENERAL, SG_DEBUG, "material = " << material); + SG_LOG(SG_GENERAL, SG_DEBUG, "poly size = " << tri_poly.contours()); + SG_LOG(SG_GENERAL, SG_DEBUG, "texs size = " << tri_txs.contours()); + for ( i = 0; i < tri_poly.contours(); ++i ) + { + tri_v.clear(); + tri_n.clear(); + tri_tc.clear(); + for ( j = 0; j < tri_poly.contour_size(i); ++j ) + { + p = tri_poly.get_pt( i, j ); + index = nodes.unique_add( p ); + tri_v.push_back( index ); + + // use 'the' normal + index = normals.unique_add( vn ); + tri_n.push_back( index ); + + Point3D tc = tri_txs.get_pt( i, j ); + index = texcoords.unique_add( tc ); + tri_tc.push_back( index ); + } + tris_v.push_back( tri_v ); + tris_n.push_back( tri_n ); + tris_tc.push_back( tri_tc ); + tri_materials.push_back( material ); + } + } + + for ( k = 0; k < (int)line_polys.size(); ++k ) + { + SG_LOG(SG_GENERAL, SG_DEBUG, "tri " << k); + // TGPolygon tri_poly = rwy_tris[k]; + TGPolygon tri_poly = line_polys[k].get_tris(); + TGPolygon tri_txs = line_polys[k].get_texcoords(); + string material = line_polys[k].get_material(); + SG_LOG(SG_GENERAL, SG_DEBUG, "material = " << material); + SG_LOG(SG_GENERAL, SG_DEBUG, "poly size = " << tri_poly.contours()); + SG_LOG(SG_GENERAL, SG_DEBUG, "texs size = " << tri_txs.contours()); + for ( i = 0; i < tri_poly.contours(); ++i ) + { + tri_v.clear(); + tri_n.clear(); + tri_tc.clear(); + for ( j = 0; j < tri_poly.contour_size(i); ++j ) + { + p = tri_poly.get_pt( i, j ); + index = nodes.unique_add( p ); + tri_v.push_back( index ); + + // use 'the' normal + index = normals.unique_add( vn ); + tri_n.push_back( index ); + + Point3D tc = tri_txs.get_pt( i, j ); + index = texcoords.unique_add( tc ); + tri_tc.push_back( index ); + } + tris_v.push_back( tri_v ); + tris_n.push_back( tri_n ); + tris_tc.push_back( tri_tc ); + tri_materials.push_back( material ); + } + } + // add base points std::vector< SGVec2f > base_txs; int_list base_tc; diff --git a/src/Airports/GenAirports850/airport.hxx b/src/Airports/GenAirports850/airport.hxx index 28ef85f4..81d5555c 100644 --- a/src/Airports/GenAirports850/airport.hxx +++ b/src/Airports/GenAirports850/airport.hxx @@ -30,6 +30,14 @@ public: features.push_back( feature ); } + void AddFeatures( FeatureList* feature_list ) + { + for (int i=0; isize(); i++) + { + features.push_back( feature_list->at(i) ); + } + } + void BuildOsg( osg::Group* airport ); void BuildBtg( const string& root, const string_list& elev_src ); diff --git a/src/Airports/GenAirports850/closedpoly.cxx b/src/Airports/GenAirports850/closedpoly.cxx index 35cfaa96..36c8ff1d 100644 --- a/src/Airports/GenAirports850/closedpoly.cxx +++ b/src/Airports/GenAirports850/closedpoly.cxx @@ -45,6 +45,10 @@ void ClosedPoly::AddNode( BezNode* node ) cur_contour->push_back( node ); SG_LOG(SG_GENERAL, SG_DEBUG, "CLOSEDPOLY::ADDNODE : (" << node->GetLoc().x() << "," << node->GetLoc().y() << ")"); + + + // TODO: Create ONE linear feature for each contour. + // Parse the polys in linear feature // if recording a linear feature on the pavement, add this node // to it as well // TODO: just doing marking now, need lighting as well @@ -71,7 +75,7 @@ void ClosedPoly::AddNode( BezNode* node ) // TODO: With offset, as all pavement markings should be // a bit in from the edge SG_LOG(SG_GENERAL, SG_DEBUG, " Starting a new linear feature"); - cur_feat = new LinearFeature(NULL); + cur_feat = new LinearFeature( (char*)"none" ); cur_feat->AddNode( node ); cur_marking = node->GetMarking(); } @@ -129,7 +133,7 @@ int ClosedPoly::CloseCurContour() } } -void ClosedPoly::ConvertContour( BezContour* src, point_list *dst, bool reverse ) +void ClosedPoly::ConvertContour( BezContour* src, point_list *dst ) { BezNode* prevNode; BezNode* curNode; @@ -151,19 +155,6 @@ void ClosedPoly::ConvertContour( BezContour* src, point_list *dst, bool reverse // clear anything in this point list dst->empty(); - if (reverse) - { - start = src->size()-1; - end = -1; - inc = -1; - } - else - { - start = 0; - end = src->size(); - inc = 1; - } - // iterate through each bezier node in the contour for (i=0; i <= src->size()-1; i++) { @@ -486,7 +477,7 @@ int ClosedPoly::Finish() if (boundary != NULL) { // create the boundary - ConvertContour( boundary, &dst_contour, false ); + ConvertContour( boundary, &dst_contour ); // and add it to the geometry pre_tess.add_contour( dst_contour, 0 ); @@ -495,7 +486,7 @@ int ClosedPoly::Finish() for (int i=0; i #include #include @@ -12,375 +10,254 @@ #include #include -int LinearFeature::Finish( osg::Group* airport ) +#include + +#include "beznode.hxx" +#include "linearfeature.hxx" +#include "math.h" + +void LinearFeature::ConvertContour( BezContour* src ) { - BezNode* node; - int i, j; - int prev_dir = 0; - double direction; - double dist1, dist2; - - printf("Finish a %s Linear Feature with %d verticies\n", closed ? "closed" : "open", contour.size()); - - BezNode* prevNode; - BezNode* curNode; - BezNode* nextNode; - + BezNode* prevNode; + BezNode* curNode; + BezNode* nextNode; + Point3D prevLoc; Point3D curLoc; Point3D nextLoc; + Point3D cp1; + Point3D cp2; - Point3D st_cur1; - Point3D st_cur2; - double st_curx, st_cury, az2; + int curve_type = CURVE_LINEAR; + Marking* cur_mark = NULL; + int i; - // create a DrawElement for the stripe triangle strip - int stripe_idx = 0; - int cur_marking = 0; + SG_LOG(SG_GENERAL, SG_DEBUG, "Creating a contour with " << src->size() << " nodes"); - osg::Vec3dArray* v_stripe = new osg::Vec3dArray; + // clear anything in the point list + points.empty(); - for (i=0; isize()-1; i++) { - printf("\nHandling Node %d\n\n", i ); + SG_LOG(SG_GENERAL, SG_DEBUG, "\nHandling Node " << i << "\n\n"); if (i == 0) { - // if closed, set prev node to last in the contour - if (closed) - { - prevNode = contour.at( contour.size()-1 ); - } - else - { - prevNode = NULL; - } + // set prev node to last in the contour, as all contours must be closed + prevNode = src->at( src->size()-1 ); } else { - prevNode = contour.at( i-1 ); + // otherwise, it's just the previous index + prevNode = src->at( i-1 ); } - curNode = contour.at(i); + curNode = src->at(i); - if (isize() - 1) { - nextNode = contour.at(i+1); + nextNode = src->at(i+1); } else { - // if closed, set next node to the first in the contour - if (closed) + // for the last node, next is the first. as all contours are closed + nextNode = src->at(0); + } + + //////////////////////////////////////////////////////////////////////////////////// + // remember the index for the starting stopping of marks on the converted contour + + // are we watching a mark for the end? + if (cur_mark) + { + if (curNode->GetMarking() != cur_mark->type) { - nextNode = contour.at(0); - } - else - { - nextNode = NULL; + // amrking has ended, or changed + cur_mark->end_idx = points.size(); + marks.push_back(cur_mark); + cur_mark = NULL; } } + + // should we start a new mark? + if (cur_mark == NULL) + { + if (curNode->GetMarking()) + { + // we aren't watching a mark, and this node has one + cur_mark = new Marking; + cur_mark->type = curNode->GetMarking(); + cur_mark->start_idx = points.size(); + } + } + //////////////////////////////////////////////////////////////////////////////////// + // determine the type of curve from prev (just to get correct prev location) // once we start drawing the curve from cur to next, we can just remember the prev loc - if (prevNode) - { - if (prevNode->HasNextCp()) - { - // curve from prev is cubic or quadratic - if(curNode->HasPrevCp()) - { - // curve from prev is cubic : calculate the last location on the curve - prevLoc = CalculateCubicLocation( prevNode->GetLoc(), prevNode->GetNextCp(), curNode->GetPrevCp(), curNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (BEZIER_DETAIL-1) ); - } - else - { - // curve from prev is quadratic : use prev node next cp - prevLoc = CalculateQuadraticLocation( prevNode->GetLoc(), prevNode->GetNextCp(), curNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (BEZIER_DETAIL-1) ); - } - } - else - { - // curve from prev is quadratic or linear - if( curNode->HasPrevCp() ) - { - // curve from prev is quadratic : calculate the last location on the curve - prevLoc = CalculateQuadraticLocation( prevNode->GetLoc(), curNode->GetPrevCp(), curNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (BEZIER_DETAIL-1) ); - } - else - { - // curve from prev is linear : just use prev node location - prevLoc = prevNode->GetLoc(); - } - } - } - else + if (prevNode->HasNextCp()) { - prevLoc = Point3D(0.0f, 0.0f, 0.0f); - } - - int curve_type = CURVE_LINEAR; - Point3D cp1; - Point3D cp2; - - if ( nextNode) - { - // now determine how we will iterate through cur node to next node - if( curNode->HasNextCp() ) + // curve from prev is cubic or quadratic + if(curNode->HasPrevCp()) { - // next curve is cubic or quadratic - if( nextNode->HasPrevCp() ) - { - // curve is cubic : need both control points - curve_type = CURVE_CUBIC; - cp1 = curNode->GetNextCp(); - cp2 = nextNode->GetPrevCp(); - } - else - { - // curve is quadratic using current nodes cp as the cp - curve_type = CURVE_QUADRATIC; - cp1 = curNode->GetNextCp(); - } + // curve from prev is cubic : calculate the last location on the curve + prevLoc = CalculateCubicLocation( prevNode->GetLoc(), prevNode->GetNextCp(), curNode->GetPrevCp(), curNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (BEZIER_DETAIL-1) ); } else { - // next curve is quadratic or linear - if( nextNode->HasPrevCp() ) - { - // curve is quadratic using next nodes cp as the cp - curve_type = CURVE_QUADRATIC; - cp1 = nextNode->GetPrevCp(); - } - else - { - // curve is linear - curve_type = CURVE_LINEAR; - } + // curve from prev is quadratic : use prev node next cp + prevLoc = CalculateQuadraticLocation( prevNode->GetLoc(), prevNode->GetNextCp(), curNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (BEZIER_DETAIL-1) ); + } + } + else + { + // curve from prev is quadratic or linear + if( curNode->HasPrevCp() ) + { + // curve from prev is quadratic : calculate the last location on the curve + prevLoc = CalculateQuadraticLocation( prevNode->GetLoc(), curNode->GetPrevCp(), curNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (BEZIER_DETAIL-1) ); + } + else + { + // curve from prev is linear : just use prev node location + prevLoc = prevNode->GetLoc(); + } + } + + // now determine how we will iterate from current node to next node + if( curNode->HasNextCp() ) + { + // next curve is cubic or quadratic + if( nextNode->HasPrevCp() ) + { + // curve is cubic : need both control points + curve_type = CURVE_CUBIC; + cp1 = curNode->GetNextCp(); + cp2 = nextNode->GetPrevCp(); + } + else + { + // curve is quadratic using current nodes cp as the cp + curve_type = CURVE_QUADRATIC; + cp1 = curNode->GetNextCp(); } } else { - curve_type = CURVE_NONE; + // next curve is quadratic or linear + if( nextNode->HasPrevCp() ) + { + // curve is quadratic using next nodes cp as the cp + curve_type = CURVE_QUADRATIC; + cp1 = nextNode->GetPrevCp(); + } + else + { + // curve is linear + curve_type = CURVE_LINEAR; + } } // initialize current location curLoc = curNode->GetLoc(); - switch( curve_type ) + if (curve_type != CURVE_LINEAR) { - case CURVE_QUADRATIC: - case CURVE_CUBIC: - for (int p=0; pGetLoc(), cp1, nextNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (p+1) ); - } - else - { - nextLoc = CalculateCubicLocation( curNode->GetLoc(), cp1, cp2, nextNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (p+1) ); - } - - // set the verticies - // convert from lat/lon to geodisc - // (maybe later) - check some simgear objects... - // printf("Added vertex at %lf,%lf\n", - // add the pavement vertex - if (p==0) - { - printf("adding Curve Anchor node (type %d) at (%lf,%lf)\n", curve_type, curLoc.x(), curLoc.y()); - } - else - { - printf(" add bezier node (type %d) at (%lf,%lf)\n", curve_type, curLoc.x(), curLoc.y()); - } - - // find the average direction at this vertex... - direction = CalcMarkingVerticies( &prevLoc, &curLoc, &nextLoc, -1, &prev_dir, &dist1, &dist2 ); - - printf("got dir for bezier : prev_dir %d, dist1 %lf, dist2 %lf\n", prev_dir, dist1, dist2); - - // distance can't be constant - it's the hypotenous of a right triangler with a constant offset from the outer rim. - geo_direct_wgs_84( curLoc.x(), curLoc.y(), direction, dist1, &st_curx, &st_cury, &az2 ); - st_cur1 = Point3D( st_curx, st_cury, 0.0f ); - v_stripe->push_back( SGPoint3DtoOSGVec3d(st_cur1) ); - - geo_direct_wgs_84( curLoc.x(), curLoc.y(), direction, dist2, &st_curx, &st_cury, &az2 ); - st_cur2 = Point3D( st_curx, st_cury, 0.0f ); - v_stripe->push_back( SGPoint3DtoOSGVec3d(st_cur2) ); - - printf("node at (%lf,%lf) has stripe verticies (%lf,%lf) and (%lf,%lf)\n", - curLoc.x(), curLoc.y(), - st_cur1.x(), st_cur1.y(), - st_cur2.x(), st_cur2.y() - ); - - // now set set prev and cur locations for the next iteration - prevLoc = curLoc; - curLoc = nextLoc; + nextLoc = CalculateQuadraticLocation( curNode->GetLoc(), cp1, nextNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (p+1) ); + } + else + { + nextLoc = CalculateCubicLocation( curNode->GetLoc(), cp1, cp2, nextNode->GetLoc(), (1.0f/BEZIER_DETAIL) * (p+1) ); } - break; - case CURVE_LINEAR: - nextLoc = nextNode->GetLoc(); + // add the feature vertex + points.push_back( curLoc ); - printf("adding Linear Anchor node at (%lf,%lf)\n", curLoc.x(), curLoc.y()); + if (p==0) + { + SG_LOG(SG_GENERAL, SG_DEBUG, "adding Curve Anchor node (type " << curve_type << ") at (" << curLoc.x() << "," << curLoc.y() << ")"); + } + else + { + SG_LOG(SG_GENERAL, SG_DEBUG, " add bezier node (type " << curve_type << ") at (" << curLoc.x() << "," << curLoc.y() << ")"); + } - // find the average direction at this vertex... - direction = CalcMarkingVerticies( &prevLoc, &curLoc, &nextLoc, -1, &prev_dir, &dist1, &dist2 ); + // now set set prev and cur locations for the next iteration + prevLoc = curLoc; + curLoc = nextLoc; + } + } + else + { + nextLoc = nextNode->GetLoc(); - printf("got dir for linear : prev_dir %d, dist1 %lf, dist2 %lf\n", prev_dir, dist1, dist2); + // just add the one vertex - linear + points.push_back( curLoc ); - // distance can't be constant - it's the hypotenous of a right triangler with a constant offset from the outer rim. - printf("calc direct: curLoc is (%lf,%lf), direction is %lf, dist is %lf\n", curLoc.x(), curLoc.y(), direction, dist1); - - geo_direct_wgs_84( curLoc.x(), curLoc.y(), direction, dist1, &st_curx, &st_cury, &az2 ); - st_cur1 = Point3D( st_curx, st_cury, 0.0f ); - - v_stripe->push_back( SGPoint3DtoOSGVec3d(st_cur1) ); - - geo_direct_wgs_84( curLoc.x(), curLoc.y(), direction, dist2, &st_curx, &st_cury, &az2 ); - st_cur2 = Point3D( st_curx, st_cury, 0.0f ); - v_stripe->push_back( SGPoint3DtoOSGVec3d(st_cur2) ); - - printf("node at (%lf,%lf) has stripe verticies (%lf,%lf) and (%lf,%lf)\n", - curLoc.x(), curLoc.y(), - st_cur1.x(), st_cur1.y(), - st_cur2.x(), st_cur2.y() - ); - break; - - case CURVE_NONE: - nextLoc = Point3D(0.0f, 0.0f, 0.0f); - - // we need to add the last verticies based on cur and prev position. - // find the average direction at this vertex... - direction = CalcMarkingVerticies( &prevLoc, &curLoc, &nextLoc, -1, &prev_dir, &dist1, &dist2 ); - - printf("got dir for term points : prev_dir %lf, dist1 %lf, dist2 %lf\n", prev_dir, dist1, dist2); - - // distance can't be constant - it's the hypotenous of a right triangler with a constant offset from the outer rim. - geo_direct_wgs_84( curLoc.x(), curLoc.y(), direction, dist1, &st_curx, &st_cury, &az2 ); - st_cur1 = Point3D( st_curx, st_cury, 0.0f ); - v_stripe->push_back( SGPoint3DtoOSGVec3d(st_cur1) ); - - geo_direct_wgs_84( curLoc.x(), curLoc.y(), direction, dist2, &st_curx, &st_cury, &az2 ); - st_cur2 = Point3D( st_curx, st_cury, 0.0f ); - v_stripe->push_back( SGPoint3DtoOSGVec3d(st_cur2) ); - - printf("node at (%lf,%lf) has stripe verticies (%lf,%lf) and (%lf,%lf)\n", - curLoc.x(), curLoc.y(), - st_cur1.x(), st_cur1.y(), - st_cur2.x(), st_cur2.y() - ); - break; + SG_LOG(SG_GENERAL, SG_DEBUG, "adding Linear Anchor node at (" << curLoc.x() << "," << curLoc.y() << ")"); } } - - printf("End feature %d \n", v_stripe->size() ); - airport->addChild(FinishMarking( v_stripe ) ); -} - -int LinearFeature::BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing ) -{ - string material; - - return 1; } -// this should be in the class -// TODO: Should Be AddMidMarkingVerticies - and handle offset (used in LinearFeature::Finish only) -double CalcMiddleMarkingVerticies( Point3D *prev, Point3D *cur, Point3D *next, int wind, int *prev_dir, double *dist1, double *dist2 ) +Point3D LinearFeature::OffsetPointMiddle( Point3D *prev, Point3D *cur, Point3D *next, double offset_by ) { - int turn_direction; - bool reverse_dir = false; double offset_dir; double next_dir; double az1, az2; double dist; + double pt_x, pt_y; - printf("Find averate angle for mark: prev (%lf,%lf), cur(%lf,%lf), next(%lf,%lf)\n", prev->x(), prev->y(), cur->x(), cur->y(), next->x(), next->y()); + SG_LOG(SG_GENERAL, SG_DEBUG, "Find average angle for contour: prev (" << *prev << "), " + "cur (" << *cur << "), " + "next (" << *next << ")" ); // first, find if the line turns left or right ar src // for this, take the cross product of the vectors from prev to src, and src to next. // if the cross product is negetive, we've turned to the left // if the cross product is positive, we've turned to the right // if the cross product is 0, then we need to use the direction passed in - SGVec3d dir1 = cur->toSGVec3d() - prev->toSGVec3d(); + SGVec3d dir1 = prev->toSGVec3d() - cur->toSGVec3d(); dir1 = normalize(dir1); - printf("normalized dir1 is (%lf,%lf)\n", dir1.x(), dir1.y()); - SGVec3d dir2 = next->toSGVec3d() - cur->toSGVec3d(); dir2 = normalize(dir2); - printf("normalized dir2 is (%lf,%lf)\n", dir2.x(), dir2.y()); - - SGVec3d cp = cross(dir1,dir2); - if (cp.z() < 0.0) - { - turn_direction = -1; - } - else if (cp.z() > 0.0) - { - turn_direction = 1; - } - else - { - turn_direction = 0; - } - - printf("turn direction is %d\n", turn_direction); - // Now find the average - SGVec3d avg = -dir1 + dir2; - - printf("avg is (%lf,%lf)\n", avg.x(), avg.y()); - - // now determine which way the direction needs to point - if ((wind == -1) && (turn_direction == 1)) - { - reverse_dir = true; - } - if ((wind == 1) && (turn_direction == -1)) - { - reverse_dir = true; - } - - printf("reverse dir is %d\n", reverse_dir); + SGVec3d avg = dir1 + dir2; + avg = normalize(avg); // find the offset angle - geo_inverse_wgs_84( 0.0f, 0.0f, avg.x(), avg.y(), &offset_dir, &az2, &dist); - if (reverse_dir) - { - offset_dir += 180; - while (offset_dir >= 360.0) - { - offset_dir -= 360.0; - } - } - printf("offset direction is %lf\n", offset_dir); + geo_inverse_wgs_84( 0.0f, 0.0f, avg.y(), avg.x(), &offset_dir, &az2, &dist); // find the direction to the next point - geo_inverse_wgs_84( cur->x(), cur->y(), next->x(), next->y(), &next_dir, &az2, &dist); - printf("next direction is %lf\n", next_dir); + geo_inverse_wgs_84( cur->y(), cur->x(), next->y(), next->x(), &next_dir, &az2, &dist); // calculate correct distance for the offset point - *dist1 = (-LINE_WIDTH)/sin(SGMiscd::deg2rad(next_dir-offset_dir)); - *dist2 = (LINE_WIDTH)/sin(SGMiscd::deg2rad(next_dir-offset_dir)); + dist = (offset_by)/sin(SGMiscd::deg2rad(offset_dir-next_dir)); - return offset_dir; + SG_LOG(SG_GENERAL, SG_DEBUG, "heading is " << offset_dir << " distance is " << dist ); + + // calculate the point from cur + geo_direct_wgs_84( cur->y(), cur->x(), offset_dir, dist, &pt_y, &pt_x, &az2 ); + + return Point3D(pt_x, pt_y, 0.0f); } -// TODO: Should Be AddStartMarkingVerticies - and handle offset (used in LinearFeature::Finish only) -double CalcStartMarkingVerticies( Point3D *cur, Point3D *next, int wind, int *prev_dir, double *dist1, double *dist2 ) +Point3D LinearFeature::OffsetPointFirst( Point3D *cur, Point3D *next, double offset_by ) { double offset_dir; double az1, az2; double dist; + double pt_x, pt_y; - printf("Find start angle for mark: cur(%lf,%lf), next(%lf,%lf)\n", cur->x(), cur->y(), next->x(), next->y()); + SG_LOG(SG_GENERAL, SG_DEBUG, "Find OffsetPoint at Start : cur (" << *cur << "), " + "next (" << *next << ")" ); // find the offset angle geo_inverse_wgs_84( cur->x(), cur->y(), next->x(), next->y(), &offset_dir, &az2, &dist); @@ -390,23 +267,24 @@ double CalcStartMarkingVerticies( Point3D *cur, Point3D *next, int wind, int *pr offset_dir += 360; } - printf("offset direction is %lf\n", offset_dir); + SG_LOG(SG_GENERAL, SG_DEBUG, "heading is " << offset_dir << " distance is " << offset_by ); - // calculate correct distance for the offset point - *dist1 = (-LINE_WIDTH); - *dist2 = (LINE_WIDTH); + // calculate the point from cur + geo_direct_wgs_84( cur->y(), cur->x(), offset_dir, offset_by, &pt_y, &pt_x, &az2 ); - return offset_dir; + return Point3D(pt_x, pt_y, 0.0f); } // TODO: Should Be AddEndMarkingVerticies - and handle offset (used in LinearFeature::Finish only) -double CalcEndMarkingVerticies( Point3D *prev, Point3D *cur, int wind, int *prev_dir, double *dist1, double *dist2 ) +Point3D LinearFeature::OffsetPointLast( Point3D *prev, Point3D *cur, double offset_by ) { double offset_dir; double az1, az2; double dist; + double pt_x, pt_y; - printf("Find end angle for mark: prev(%lf,%lf), cur(%lf,%lf)\n", prev->x(), prev->y(), cur->x(), cur->y()); + SG_LOG(SG_GENERAL, SG_DEBUG, "Find OffsetPoint at End : prev (" << *prev << "), " + "cur (" << *cur << ")" ); // find the offset angle geo_inverse_wgs_84( prev->x(), prev->y(), cur->x(), cur->y(), &offset_dir, &az2, &dist); @@ -416,135 +294,177 @@ double CalcEndMarkingVerticies( Point3D *prev, Point3D *cur, int wind, int *prev offset_dir += 360; } - printf("offset direction is %lf\n", offset_dir); + SG_LOG(SG_GENERAL, SG_DEBUG, "heading is " << offset_dir << " distance is " << offset_by ); - // calculate correct distance for the offset point - *dist1 = (-LINE_WIDTH); - *dist2 = (LINE_WIDTH); + // calculate the point from cur + geo_direct_wgs_84( cur->y(), cur->x(), offset_dir, offset_by, &pt_y, &pt_x, &az2 ); - return offset_dir; + return Point3D(pt_x, pt_y, 0.0f); } -// TODO: Should Be AddMarkingVerticies - and handle offset (used in LinearFeature::Finish only) -double CalcMarkingVerticies( Point3D *prev, Point3D *cur, Point3D *next, int wind, int *prev_dir, double *dist1, double *dist2 ) + + +int LinearFeature::Finish() { - double offset_dir; - - // first, we need to see if we want to average the directions (we have both prev, and next) - if ( (prev->x() == 0.0f) && (prev->y() == 0.0f) ) + TGPolygon poly; + TGSuperPoly sp; + TGTexParams tp; + Point3D prev_inner, prev_outer; + Point3D cur_inner, cur_outer; + double heading; + double dist; + double az2; + int i, j; + string material; + + + // create the inner and outer boundaries to generate polys + // this generates 2 point lists for the contours, and remembers + // the start stop points for markings + ConvertContour( &contour ); + + // now generate the supoerpoly and texparams list + for (i=0; ix() == 0.0f) && (next->y() == 0.0f) ) - { - // direction is 90 degrees less than from current to next - offset_dir = CalcEndMarkingVerticies( prev, cur, wind, prev_dir, dist1, dist2 ); - printf("got dist 1: %lf, dist2: %lf\n", *dist1, *dist2); - } - else - { - offset_dir = CalcMiddleMarkingVerticies( prev, cur, next, wind, prev_dir, dist1, dist2 ); - printf("got dist 1: %lf, dist2: %lf\n", *dist1, *dist2); - } + prev_inner = Point3D(0.0f, 0.0f, 0.0f); + prev_outer = Point3D(0.0f, 0.0f, 0.0f); - printf("return from CalcMarkingVerticies: dirst1: %lf, dist2: %lf\n", *dist1, *dist2); - - return offset_dir; -} - -// need to refactor this stuff. -osg::Geode* FinishMarking( osg::Vec3dArray* verticies ) -{ - osg::Geometry* stripe = NULL; - osg::Geode* geode_stripe = NULL; - osg::StateSet* ss_stripe = NULL; - osg::PolygonMode* polymode = NULL; - osg::Vec4Array* col_stripe = NULL; - int j; - - // set up polygon offset - osg::PolygonOffset* polyoffset = new osg::PolygonOffset; - polyoffset->setFactor(-1.00f); - polyoffset->setUnits(-1.00f); - - polymode = new osg::PolygonMode; - polymode->setMode( osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE ); - - col_stripe = new osg::Vec4Array; - col_stripe->push_back(osg::Vec4(1.0f,1.0f,0.0f,1.0f)); - - // Create a new stripe geometry - stripe = new osg::Geometry; - stripe->setColorArray(col_stripe); - stripe->setColorBinding(osg::Geometry::BIND_OVERALL); - - ss_stripe = new osg::StateSet(); - ss_stripe->setAttributeAndModes(polyoffset,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON); -#if WIREFRAME - ss_stripe->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON); -#endif - geode_stripe = new osg::Geode(); - geode_stripe->setStateSet(ss_stripe); - - stripe->setVertexArray(verticies); - - // create the index array for the stripe - osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(GL_TRIANGLE_STRIP,verticies->size())); - - for (j=0; jsize(); j++) - { - drawElements[j] = j; - } - - for (int k=0; kaddPrimitiveSet(&drawElements); - - geode_stripe->addDrawable(stripe); - - return geode_stripe; -} - -// TODO: Add this into Linear Feature -osg::Vec3dArray* StartMarking() -{ - osg::Vec3dArray* v_marking = new osg::Vec3dArray; - - return v_marking; -} - -// TODO: move this into LinearFeature -osg::Vec3dArray* CheckMarking(int cur_marking, int new_marking, osg::Vec3dArray* v_marking, osg::Group* airport) -{ - // check if we need to finish a marking - printf("Check Marking : current is %d, new is %d\n", cur_marking, new_marking); - - if ( (v_marking != NULL) && (cur_marking != new_marking) ) - { - printf("End current marking %d and start new marking %d : mark poly has %d verticies\n", cur_marking, new_marking, v_marking->size() ); - for (int k=0; ksize(); k++) + // which material for this mark? + switch( marks[i]->type ) { - printf("vertex %d is (%lf, %lf)\n", k, v_marking->at(k).x(), v_marking->at(k).y()); + case LF_NONE: + case LF_SOLID_YELLOW: + case LF_BROKEN_YELLOW: + case LF_SOLID_DBL_YELLOW: + case LF_RUNWAY_HOLD: + case LF_OTHER_HOLD: + case LF_ILS_HOLD: + case LF_SAFETYZONE_CENTERLINE: + case LF_SINGLE_LANE_QUEUE: + case LF_DOUBLE_LANE_QUEUE: + + case LF_B_SOLID_YELLOW: + case LF_B_BROKEN_YELLOW: + case LF_B_SOLID_DBL_YELLOW: + case LF_B_RUNWAY_HOLD: + case LF_B_OTHER_HOLD: + case LF_B_ILS_HOLD: + case LF_B_SAFETYZONE_CENTERLINE: + case LF_B_SINGLE_LANE_QUEUE: + case LF_B_DOUBLE_LANE_QUEUE: + + case LF_SOLID_WHITE: + case LF_CHECKERBOARD_WHITE: + case LF_BROKEN_WHITE: + + case LF_BIDIR_GREEN: + case LF_OMNIDIR_BLUE: + case LF_UNIDIR_CLOSE_AMBER: + case LF_UNIDIR_CLOSE_AMBER_PULSE: + case LF_BIDIR_GREEN_AMBER: + case LF_OMNIDIR_RED: + material = "gloff_lf_b_solid_yellow"; + break; + + default: + SG_LOG(SG_GENERAL, SG_DEBUG, "ClosedPoly::BuildBtg: unknown material " << marks[i]->type ); + exit(1); } - // END THE CURRENT MARKING - airport->addChild(FinishMarking( v_marking ) ); - v_marking = NULL; - } - - // Start recording a new marking - if ( (v_marking == NULL) && (new_marking != 0) ) - { - // start a new marking - printf("Start new marking %d\n", new_marking); - - v_marking = StartMarking(); - } + for (j = marks[i]->start_idx; j < marks[i]->end_idx; j++) + { + // for each point on the PointsList, generate a quad from + // start to next, offset by 2 distnaces from the edge - return v_marking; + if (j == 0) + { + // first point on the contour - offset heading is 90deg + cur_outer = OffsetPointFirst( &points[j], &points[j+1], 0.4 ); + cur_inner = OffsetPointFirst( &points[j], &points[j+1], 0.5 ); + } + else if (j == points.size()-1) + { + // last point on the contour - offset heading is 90deg + cur_outer = OffsetPointFirst( &points[j-1], &points[j], 0.4 ); + cur_inner = OffsetPointFirst( &points[j-1], &points[j], 0.5 ); + } + else + { + cur_outer = OffsetPointMiddle( &points[j-1], &points[j], &points[j+1], 0.4 ); + cur_inner = OffsetPointMiddle( &points[j-1], &points[j], &points[j+1], 0.5 ); + } + + if ( (prev_inner.x() != 0.0f) && (prev_inner.y() != 0.0f) ) + { + geo_inverse_wgs_84( prev_outer.y(), prev_outer.x(), cur_outer.y(), cur_outer.x(), &heading, &az2, &dist); + + poly.erase(); + poly.add_node( 0, prev_outer ); + poly.add_node( 0, prev_inner ); + poly.add_node( 0, cur_inner ); + poly.add_node( 0, cur_outer ); + + sp.erase(); + sp.set_poly( poly ); + sp.set_material( material ); + feature_polys.push_back(sp); + + tp = TGTexParams( prev_inner, 0.1, 1.0, heading ); + feature_tps.push_back(tp); + } + + prev_outer = cur_outer; + prev_inner = cur_inner; + } + } +} + +int LinearFeature::BuildBtg(float alt_m, superpoly_list* line_polys, texparams_list* line_tps, TGPolygon* line_accum ) +{ + string material; + int j, k; + +#if 0 + + // verify the poly has been generated + if ( pre_tess.contours() ) + { + SG_LOG(SG_GENERAL, SG_DEBUG, "LinearFeature::BuildBtg: original poly has " << pre_tess.contours() << " contours"); + + // do this before clipping and generating the base + pre_tess = remove_dups( pre_tess ); + pre_tess = reduce_degeneracy( pre_tess ); + + for (int c=0; cpush_back( sp ); + SG_LOG(SG_GENERAL, SG_DEBUG, "clipped = " << clipped.contours()); + *line_accum = tgPolygonUnion( pre_tess, *line_accum ); + tp = TGTexParams( pre_tess.get_pt(0,0), 0.2 /* TODO poly width */, 1.0 /* TODO poly length */, texture_heading ); + texparams->push_back( tp ); + } +#endif + + return 1; } diff --git a/src/Airports/GenAirports850/linearfeature.hxx b/src/Airports/GenAirports850/linearfeature.hxx index adf7ece1..19b9e6c8 100644 --- a/src/Airports/GenAirports850/linearfeature.hxx +++ b/src/Airports/GenAirports850/linearfeature.hxx @@ -11,6 +11,49 @@ using std::string; + +#define LF_NONE (0) +#define LF_SOLID_YELLOW (1) +#define LF_BROKEN_YELLOW (2) +#define LF_SOLID_DBL_YELLOW (3) +#define LF_RUNWAY_HOLD (4) +#define LF_OTHER_HOLD (5) +#define LF_ILS_HOLD (6) +#define LF_SAFETYZONE_CENTERLINE (7) +#define LF_SINGLE_LANE_QUEUE (8) +#define LF_DOUBLE_LANE_QUEUE (9) + +#define LF_B_SOLID_YELLOW (51) +#define LF_B_BROKEN_YELLOW (52) +#define LF_B_SOLID_DBL_YELLOW (53) +#define LF_B_RUNWAY_HOLD (54) +#define LF_B_OTHER_HOLD (55) +#define LF_B_ILS_HOLD (56) +#define LF_B_SAFETYZONE_CENTERLINE (57) +#define LF_B_SINGLE_LANE_QUEUE (58) +#define LF_B_DOUBLE_LANE_QUEUE (59) + +#define LF_SOLID_WHITE (20) +#define LF_CHECKERBOARD_WHITE (21) +#define LF_BROKEN_WHITE (22) + +#define LF_BIDIR_GREEN (101) +#define LF_OMNIDIR_BLUE (102) +#define LF_UNIDIR_CLOSE_AMBER (103) +#define LF_UNIDIR_CLOSE_AMBER_PULSE (104) +#define LF_BIDIR_GREEN_AMBER (105) +#define LF_OMNIDIR_RED (106) + +struct Marking +{ +public: + int type; + int start_idx; + int end_idx; +}; +typedef std::vector MarkingList; + + class LinearFeature { public: @@ -24,40 +67,45 @@ public: { strcpy( description, "none" ); } - - offset = 0.0f; - closed = false; } - + void AddNode( BezNode* b ) { contour.push_back( b ); } - void SetClosed() - { - closed = true; - } + int Finish(); + int BuildOsg( osg::Group* airport ); + int BuildBtg( float alt_m, superpoly_list* line_polys, texparams_list* line_tps, TGPolygon* line_accum ); - int Finish( osg::Group* airport ); - int BuildBtg( float alt_m, superpoly_list* rwy_polys, texparams_list* texparams, TGPolygon* accum, TGPolygon* apt_base, TGPolygon* apt_clearing ); - private: + Point3D OffsetPointFirst( Point3D *cur, Point3D *next, double offset_by ); + Point3D OffsetPointMiddle( Point3D *prev, Point3D *cur, Point3D *next, double offset_by ); + Point3D OffsetPointLast( Point3D *prev, Point3D *cur, double offset_by ); + + MarkingList marks; + Marking* cur_mark; + + void ConvertContour( BezContour* src ); + + // text description char description[256]; - // contour definition + // contour definition (each beznode has marking type) BezContour contour; - // TODO : Implement offset - double offset; - - bool closed; + // contour definition after bezier interpolation + point_list points; + + superpoly_list feature_polys; + texparams_list feature_tps; }; typedef std::vector FeatureList; // add this to the class -extern double CalcMarkingVerticies( Point3D *prev, Point3D *cur, Point3D *next, int wind, int *prev_dir, double *dist1, double *dist2 ); + +extern double CalcMarkingVerticies( Point3D *prev, Point3D *cur, Point3D *next, double *dist1, double *dist2 ); // don't know what to do with these extern osg::Geode* FinishMarking( osg::Vec3dArray* verticies );