]> git.mxchange.org Git - flightgear.git/commitdiff
Handle corner nodes separately from the rest of the fitted nodes.
authorcurt <curt>
Sat, 27 Mar 1999 05:30:12 +0000 (05:30 +0000)
committercurt <curt>
Sat, 27 Mar 1999 05:30:12 +0000 (05:30 +0000)
Add fitted nodes in after corners and polygon nodes since the fitted nodes
  are less important.  Subsequent nodes will "snap" to previous nodes if
  they are "close enough."
Need to manually divide segments to prevent "T" intersetions which can
  confound the triangulator.  Hey, I got to use a recursive method!
Pass along correct triangle attributes to output file generator.
Do fine grained node snapping for corners and polygons, but course grain
  node snapping for fitted terrain nodes.

Triangulate/triangle.cxx
Triangulate/triangle.hxx
Triangulate/trieles.hxx
Triangulate/trinodes.cxx
Triangulate/trinodes.hxx
Triangulate/trisegs.cxx
Triangulate/trisegs.hxx

index b1beaa79f6f9802f8837fe281f026a33250f1331..5aa396721cfcf837ea0a02a3a7df565edba3265a 100644 (file)
@@ -37,7 +37,8 @@ FGTriangle::~FGTriangle( void ) {
 
 // populate this class based on the specified gpc_polys list
 int 
-FGTriangle::build( const fitnode_list& fit_list, 
+FGTriangle::build( const fitnode_list& corner_list,
+                  const fitnode_list& fit_list, 
                   const FGgpcPolyList& gpc_polys )
 {
     FGTriPoly poly;
@@ -48,18 +49,20 @@ FGTriangle::build( const fitnode_list& fit_list,
     // char junkn[256];
     // FILE *junkfp;
 
-    // traverse the dem fit list and gpc_polys building a unified node
-    // list and converting the polygons so that they reference the
-    // node list by index (starting at zero) rather than listing the
-    // points explicitely
+    // traverse the dem corner and fit lists and gpc_polys building a
+    // unified node list and converting the polygons so that they
+    // reference the node list by index (starting at zero) rather than
+    // listing the points explicitely
 
+    // first the corners since these are important
     const_fitnode_list_iterator f_current, f_last;
-    f_current = fit_list.begin();
-    f_last = fit_list.end();
+    f_current = corner_list.begin();
+    f_last = corner_list.end();
     for ( ; f_current != f_last; ++f_current ) {
        index = in_nodes.unique_add( *f_current );
     }
 
+    // next process the polygons
     gpc_polygon *gpc_poly;
     const_gpcpoly_iterator current, last;
 
@@ -87,6 +90,8 @@ FGTriangle::build( const fitnode_list& fit_list,
            }
 
            for ( int j = 0; j < gpc_poly->num_contours; j++ ) {
+               cout << " processing contour, nodes = " 
+                    << gpc_poly->contour[j].num_vertices << endl;
 
                poly.erase();
 
@@ -115,6 +120,13 @@ FGTriangle::build( const fitnode_list& fit_list,
        }
     }
 
+    // last, do the rest of the height nodes
+    f_current = fit_list.begin();
+    f_last = fit_list.end();
+    for ( ; f_current != f_last; ++f_current ) {
+       index = in_nodes.course_add( *f_current );
+    }
+
     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
        if ( polylist[i].size() ) {
            cout << get_area_name((AreaType)i) << " = " 
@@ -126,6 +138,7 @@ FGTriangle::build( const fitnode_list& fit_list,
     // that is used by the "Triangle" lib.
 
     int i1, i2;
+    point_list node_list = in_nodes.get_node_list();
     for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
        cout << "area type = " << i << endl;
        tripoly_list_iterator tp_current, tp_last;
@@ -139,11 +152,13 @@ FGTriangle::build( const fitnode_list& fit_list,
            for ( int j = 0; j < (int)(poly.size()) - 1; ++j ) {
                i1 = poly.get_pt_index( j );
                i2 = poly.get_pt_index( j + 1 );
-               trisegs.unique_add( FGTriSeg(i1, i2) );
+               // calc_line_params(i1, i2, &m, &b);
+               trisegs.unique_divide_and_add( node_list, FGTriSeg(i1, i2) );
            }
            i1 = poly.get_pt_index( 0 );
            i2 = poly.get_pt_index( poly.size() - 1 );
-           trisegs.unique_add( FGTriSeg(i1, i2) );
+           // calc_line_params(i1, i2, &m, &b);
+           trisegs.unique_divide_and_add( node_list, FGTriSeg(i1, i2) );
        }
     }
 
@@ -197,6 +212,7 @@ static void write_out_data(struct triangulateio *out) {
                i, out->regionlist[4*i], out->regionlist[4*i + 1],
                out->regionlist[4*i + 2]);
     }
+    fclose(fp);
 }
 
 
@@ -312,17 +328,22 @@ int FGTriangle::run_triangulate() {
     vorout.normlist = (REAL *) NULL;      // Needed only if -v switch used.
     
     // TEMPORARY
-    // write_out_data(&in);
+    write_out_data(&in);
 
     // Triangulate the points.  Switches are chosen to read and write
     // a PSLG (p), preserve the convex hull (c), number everything
     // from zero (z), assign a regional attribute to each element (A),
     // and produce an edge list (e), and a triangle neighbor list (n).
 
-    triangulate("pczq15Aen", &in, &out, &vorout);
+    string tri_options = "pczq10Aen";
+    // string tri_options = "pzAen";
+    // string tri_options = "pczq15S400Aen";
+    cout << "Triangulation with options = " << tri_options << endl;
+
+    triangulate(tri_options.c_str(), &in, &out, &vorout);
 
     // TEMPORARY
-    write_out_data(&out);
+    // write_out_data(&out);
 
     // now copy the results back into the corresponding FGTriangle
     // structures
@@ -336,13 +357,19 @@ int FGTriangle::run_triangulate() {
 
     // triangles
     int n1, n2, n3;
+    double attribute;
     for ( int i = 0; i < out.numberoftriangles; i++ ) {
        n1 = out.trianglelist[i * 3];
        n2 = out.trianglelist[i * 3 + 1];
        n3 = out.trianglelist[i * 3 + 2];
+       if ( out.numberoftriangleattributes > 0 ) {
+           attribute = out.triangleattributelist[i];
+       } else {
+           attribute = 0.0;
+       }
        // cout << "triangle = " << n1 << " " << n2 << " " << n3 << endl;
 
-       elelist.push_back( FGTriEle( n1, n2, n3 ) );
+       elelist.push_back( FGTriEle( n1, n2, n3, attribute ) );
     }
 
     // free mem allocated to the "Triangle" structures
@@ -371,6 +398,17 @@ int FGTriangle::run_triangulate() {
 
 
 // $Log$
+// Revision 1.12  1999/03/27 05:30:12  curt
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Add fitted nodes in after corners and polygon nodes since the fitted nodes
+//   are less important.  Subsequent nodes will "snap" to previous nodes if
+//   they are "close enough."
+// Need to manually divide segments to prevent "T" intersetions which can
+//   confound the triangulator.  Hey, I got to use a recursive method!
+// Pass along correct triangle attributes to output file generator.
+// Do fine grained node snapping for corners and polygons, but course grain
+//   node snapping for fitted terrain nodes.
+//
 // Revision 1.11  1999/03/23 22:02:51  curt
 // Refinements in naming and organization.
 //
index ba4fb4cbfa84ff9ca1a2dda5fc0e30e9c7bf5ec5..8106c3ab39cf0e3f0362f0a9ff828ea4a1d05846 100644 (file)
@@ -76,7 +76,9 @@ public:
     int add_nodes();
 
     // populate this class based on the specified gpc_polys list
-    int build( const fitnode_list& fit_list, const FGgpcPolyList& gpc_polys );
+    int build( const fitnode_list& corner_list, 
+              const fitnode_list& fit_list,
+              const FGgpcPolyList& gpc_polys );
 
     // front end triangulator for polygon list
     int run_triangulate();
@@ -90,6 +92,17 @@ public:
 
 
 // $Log$
+// Revision 1.9  1999/03/27 05:30:13  curt
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Add fitted nodes in after corners and polygon nodes since the fitted nodes
+//   are less important.  Subsequent nodes will "snap" to previous nodes if
+//   they are "close enough."
+// Need to manually divide segments to prevent "T" intersetions which can
+//   confound the triangulator.  Hey, I got to use a recursive method!
+// Pass along correct triangle attributes to output file generator.
+// Do fine grained node snapping for corners and polygons, but course grain
+//   node snapping for fitted terrain nodes.
+//
 // Revision 1.8  1999/03/23 22:02:52  curt
 // Refinements in naming and organization.
 //
index 8a867fc0e1e39d3a4960c69a183f206794539582..2d22c7db5ee62b8baab7bed0a9cf773fe9e6c501 100644 (file)
@@ -42,11 +42,15 @@ FG_USING_STD(vector);
 class FGTriEle {
     int n1, n2, n3;
 
+    double attribute;
+
 public:
 
     // Constructor and destructor
     inline FGTriEle( void ) { };
-    inline FGTriEle( int i1, int i2, int i3 ) { n1 = i1; n2 = i2; n3 = i3; }
+    inline FGTriEle( int i1, int i2, int i3, double a ) {
+       n1 = i1; n2 = i2; n3 = i3; attribute = a;
+    }
 
     inline ~FGTriEle( void ) { };
 
@@ -56,6 +60,9 @@ public:
     inline void set_n2( int i ) { n2 = i; }
     inline int get_n3() const { return n3; }
     inline void set_n3( int i ) { n3 = i; }
+
+    inline double get_attribute() const { return attribute; }
+    inline void set_attribute( double a ) { attribute = a; }
 };
 
 
@@ -68,6 +75,17 @@ typedef triele_list::const_iterator const_triele_list_iterator;
 
 
 // $Log$
+// Revision 1.3  1999/03/27 05:30:14  curt
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Add fitted nodes in after corners and polygon nodes since the fitted nodes
+//   are less important.  Subsequent nodes will "snap" to previous nodes if
+//   they are "close enough."
+// Need to manually divide segments to prevent "T" intersetions which can
+//   confound the triangulator.  Hey, I got to use a recursive method!
+// Pass along correct triangle attributes to output file generator.
+// Do fine grained node snapping for corners and polygons, but course grain
+//   node snapping for fitted terrain nodes.
+//
 // Revision 1.2  1999/03/23 22:02:53  curt
 // Refinements in naming and organization.
 //
index 75b5b302d594ae08976af21c2244e5b7195d8fd3..50e7df7ee8febac106936d303bf607f1dd5c2da5 100644 (file)
@@ -35,18 +35,6 @@ FGTriNodes::~FGTriNodes( void ) {
 }
 
 
-// return true of the two points are "close enough" as defined by
-// FG_PROXIMITY_EPSILON
-inline bool FGTriNodes::close_enough( const Point3D& p1, const Point3D& p2 ) {
-    if ( ( fabs(p1.x() - p2.x()) < FG_PROXIMITY_EPSILON ) &&
-        ( fabs(p1.y() - p2.y()) < FG_PROXIMITY_EPSILON ) ) {
-       return true;
-    } else {
-       return false;
-    }
-}
-
-
 // Add a point to the point list if it doesn't already exist.  Returns
 // the index (starting at zero) of the point in the list.
 int FGTriNodes::unique_add( const Point3D& p ) {
@@ -82,7 +70,46 @@ int FGTriNodes::simple_add( const Point3D& p ) {
 }
 
 
+// Add a point to the point list if it doesn't already exist.  Returns
+// the index (starting at zero) of the point in the list.  Use a
+// course proximity check
+int FGTriNodes::course_add( const Point3D& p ) {
+    point_list_iterator current, last;
+    int counter = 0;
+
+    // cout << p.x() << "," << p.y() << endl;
+
+    // see if point already exists
+    current = node_list.begin();
+    last = node_list.end();
+    for ( ; current != last; ++current ) {
+       if ( course_close_enough(p, *current) ) {
+           // cout << "found an existing match!" << endl;
+           return counter;
+       }
+       
+       ++counter;
+    }
+
+    // add to list
+    node_list.push_back( p );
+
+    return counter;
+}
+
+
 // $Log$
+// Revision 1.6  1999/03/27 05:30:15  curt
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Add fitted nodes in after corners and polygon nodes since the fitted nodes
+//   are less important.  Subsequent nodes will "snap" to previous nodes if
+//   they are "close enough."
+// Need to manually divide segments to prevent "T" intersetions which can
+//   confound the triangulator.  Hey, I got to use a recursive method!
+// Pass along correct triangle attributes to output file generator.
+// Do fine grained node snapping for corners and polygons, but course grain
+//   node snapping for fitted terrain nodes.
+//
 // Revision 1.5  1999/03/23 22:02:54  curt
 // Refinements in naming and organization.
 //
index ab1b3650403c8cc2b9491804e0b43d6274451a32..860b63034e0d2baf24d1e5ebedfebf7aaa2093ac 100644 (file)
@@ -41,6 +41,7 @@ FG_USING_STD(vector);
 
 
 #define FG_PROXIMITY_EPSILON 0.000001
+#define FG_COURSE_EPSILON 0.0003
 
 
 typedef vector < Point3D > point_list;
@@ -58,6 +59,10 @@ private:
     // FG_PROXIMITY_EPSILON
     bool close_enough( const Point3D& p, const Point3D& p );
 
+    // return true of the two points are "close enough" as defined by
+    // FG_COURSE_EPSILON
+    bool course_close_enough( const Point3D& p1, const Point3D& p2 );
+
 public:
 
     // Constructor and destructor
@@ -71,6 +76,11 @@ public:
     // Add the point with no uniqueness checking
     int simple_add( const Point3D& p );
 
+    // Add a point to the point list if it doesn't already exist.
+    // Returns the index (starting at zero) of the point in the list.
+    // Use a course proximity check
+    int course_add( const Point3D& p );
+
     // return the master node list
     inline point_list get_node_list() const { return node_list; }
 
@@ -79,10 +89,47 @@ public:
 };
 
 
+// return true of the two points are "close enough" as defined by
+// FG_PROXIMITY_EPSILON
+inline bool FGTriNodes::close_enough( const Point3D& p1, const Point3D& p2 ) {
+    if ( ( fabs(p1.x() - p2.x()) < FG_PROXIMITY_EPSILON ) &&
+        ( fabs(p1.y() - p2.y()) < FG_PROXIMITY_EPSILON ) ) {
+       return true;
+    } else {
+       return false;
+    }
+}
+
+
+// return true of the two points are "close enough" as defined by
+// FG_COURSE_EPSILON
+inline bool FGTriNodes::course_close_enough( const Point3D& p1, 
+                                            const Point3D& p2 )
+{
+    if ( ( fabs(p1.x() - p2.x()) < FG_COURSE_EPSILON ) &&
+        ( fabs(p1.y() - p2.y()) < FG_COURSE_EPSILON ) ) {
+       return true;
+    } else {
+       return false;
+    }
+}
+
+
 #endif // _TRINODES_HXX
 
 
 // $Log$
+// Revision 1.6  1999/03/27 05:30:16  curt
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Add fitted nodes in after corners and polygon nodes since the fitted nodes
+//   are less important.  Subsequent nodes will "snap" to previous nodes if
+//   they are "close enough."
+// Need to manually divide segments to prevent "T" intersetions which can
+//   confound the triangulator.  Hey, I got to use a recursive method!
+// Pass along correct triangle attributes to output file generator.
+// Do fine grained node snapping for corners and polygons, but course grain
+//   node snapping for fitted terrain nodes.
+//
 // Revision 1.5  1999/03/23 22:02:55  curt
 // Refinements in naming and organization.
 //
index 6d4ac1bb5e527df8b8857532f383138ca993c58e..62cf4d03ae9f946e7fd88a12ff4749857e2a26dc 100644 (file)
 // (Log is kept at end of this file)
 
 
+#include <Include/fg_constants.h>
+#include <Math/point3d.hxx>
+
+#include "trinodes.hxx"
 #include "trisegs.hxx"
 
 
@@ -35,15 +39,16 @@ FGTriSegments::~FGTriSegments( void ) {
 }
 
 
-// Add a point to the point list if it doesn't already exist.
-// Returns the index (starting at zero) of the point in the list.
-int FGTriSegments::unique_add( const FGTriSeg& s ) {
+// Add a segment to the segment list if it doesn't already exist.
+// Returns the index (starting at zero) of the segment in the list.
+int FGTriSegments::unique_add( const FGTriSeg& s )
+{
     triseg_list_iterator current, last;
     int counter = 0;
 
     // cout << s.get_n1() << "," << s.get_n2() << endl;
 
-    // see if point already exists
+    // check if segment already exists
     current = seg_list.begin();
     last = seg_list.end();
     for ( ; current != last; ++current ) {
@@ -62,7 +67,120 @@ int FGTriSegments::unique_add( const FGTriSeg& s ) {
 }
 
 
+// Divide segment if there are other points on it, return the divided
+// list of segments
+void FGTriSegments::unique_divide_and_add( const point_list& nodes, 
+                                          const FGTriSeg& s )
+{
+    Point3D p0 = nodes[ s.get_n1() ];
+    Point3D p1 = nodes[ s.get_n2() ];
+
+    bool found_extra = false;
+    int extra_index;
+    int counter;
+    double m, b, y_err, x_err;
+    const_point_list_iterator current, last;
+
+    // bool temp = false;
+    // if ( s == FGTriSeg( 170, 206 ) ) {
+    //   cout << "this is it!" << endl;
+    //   temp = true;
+    // }
+
+    if ( fabs(p0.x() - p1.x()) > FG_EPSILON ) {
+       // use y = mx + b
+
+       // sort these in a sensable order
+       if ( p0.x() > p1.x() ) {
+           Point3D tmp = p0;
+           p0 = p1;
+           p1 = tmp;
+       }
+
+       m = (p0.y() - p1.y()) / (p0.x() - p1.x());
+       b = p1.y() - m * p1.x();
+
+       // if ( temp ) {
+       //   cout << "m = " << m << " b = " << b << endl;
+       // }
+
+       current = nodes.begin();
+       last = nodes.end();
+       counter = 0;
+       for ( ; current != last; ++current ) {
+           if ( (current->x() > (p0.x() + FG_EPSILON)) 
+                && (current->x() < (p1.x() - FG_EPSILON)) ) {
+
+               // if ( temp ) {
+               //   cout << counter << endl;
+               // }
+
+               y_err = fabs(current->y() - (m * current->x() + b));
+
+               if ( y_err < 10 * FG_EPSILON ) {
+                   cout << "FOUND EXTRA SEGMENT NODE (Y)" << endl;
+                   cout << p0 << " < " << *current << " < "
+                        << p1 << endl;
+                   found_extra = true;
+                   extra_index = counter;
+                   break;
+               }
+           }
+           ++counter;
+       }
+    } else {
+       // use x = constant
+
+       // sort these in a sensable order
+       if ( p0.y() > p1.y() ) {
+           Point3D tmp = p0;
+           p0 = p1;
+           p1 = tmp;
+       }
+
+       current = nodes.begin();
+       last = nodes.end();
+       counter = 0;
+       for ( ; current != last; ++current ) {
+           // cout << counter << endl;
+           if ( (current->y() > p0.y()) && (current->y() < p1.y()) ) {
+               x_err = fabs(current->x() - p0.x());
+               if ( x_err < 10*FG_EPSILON ) {
+                   cout << "FOUND EXTRA SEGMENT NODE (X)" << endl;
+                   found_extra = true;
+                   extra_index = counter;
+                   break;
+               }
+           }
+           ++counter;
+       }
+    }
+
+    if ( found_extra ) {
+       // recurse with two sub segments
+       cout << "dividing " << s.get_n1() << " " << extra_index 
+            << " " << s.get_n2() << endl;
+       unique_divide_and_add( nodes, FGTriSeg( s.get_n1(), extra_index ) );
+       unique_divide_and_add( nodes, FGTriSeg( extra_index, s.get_n2() ) );
+    } else {
+       // this segment does not need to be divided, lets add it
+       unique_add( s );
+    }
+}
+
+
 // $Log$
+// Revision 1.4  1999/03/27 05:30:17  curt
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Add fitted nodes in after corners and polygon nodes since the fitted nodes
+//   are less important.  Subsequent nodes will "snap" to previous nodes if
+//   they are "close enough."
+// Need to manually divide segments to prevent "T" intersetions which can
+//   confound the triangulator.  Hey, I got to use a recursive method!
+// Pass along correct triangle attributes to output file generator.
+// Do fine grained node snapping for corners and polygons, but course grain
+//   node snapping for fitted terrain nodes.
+//
 // Revision 1.3  1999/03/23 22:02:57  curt
 // Refinements in naming and organization.
 //
index 31189d591850b35cdba450dae8a11bee616b9943..09fd5b921dc8c1838fcc6e0197099af3606e743f 100644 (file)
@@ -35,6 +35,8 @@
 
 #include <vector>
 
+#include "trinodes.hxx"
+
 FG_USING_STD(vector);
 
 
@@ -46,7 +48,10 @@ public:
 
     // Constructor and destructor
     inline FGTriSeg( void ) { };
-    inline FGTriSeg( int i1, int i2 ) { n1 = i1; n2 = i2; }
+    inline FGTriSeg( int i1, int i2 ) { 
+       n1 = i1;
+       n2 = i2;
+    }
 
     inline ~FGTriSeg( void ) { };
 
@@ -77,16 +82,27 @@ private:
 
     triseg_list seg_list;
 
+    // Divide segment if there are other points on it, return the
+    // divided list of segments
+    triseg_list divide_segment( const point_list& nodes, 
+                               const FGTriSeg& s );
+
 public:
 
     // Constructor and destructor
     FGTriSegments( void );
     ~FGTriSegments( void );
 
-    // Add a point to the point list if it doesn't already exist.
-    // Returns the index (starting at zero) of the point in the list.
+    // Add a segment to the segment list if it doesn't already exist.
+    // Returns the index (starting at zero) of the segment in the
+    // list.
     int unique_add( const FGTriSeg& s );
 
+    // Add a segment to the segment list if it doesn't already exist.
+    // Returns the index (starting at zero) of the segment in the list.
+    void unique_divide_and_add( const point_list& node_list, 
+                               const FGTriSeg& s );
+
     // return the master node list
     inline triseg_list get_seg_list() const { return seg_list; }
 
@@ -99,6 +115,17 @@ public:
 
 
 // $Log$
+// Revision 1.3  1999/03/27 05:30:18  curt
+// Handle corner nodes separately from the rest of the fitted nodes.
+// Add fitted nodes in after corners and polygon nodes since the fitted nodes
+//   are less important.  Subsequent nodes will "snap" to previous nodes if
+//   they are "close enough."
+// Need to manually divide segments to prevent "T" intersetions which can
+//   confound the triangulator.  Hey, I got to use a recursive method!
+// Pass along correct triangle attributes to output file generator.
+// Do fine grained node snapping for corners and polygons, but course grain
+//   node snapping for fitted terrain nodes.
+//
 // Revision 1.2  1999/03/20 20:33:00  curt
 // First mostly successful tile triangulation works.  There's plenty of tweaking
 // to do, but we are marching in the right direction.