Index: SRTMConGen.cpp
===================================================================
--- SRTMConGen.cpp	(revision 2100)
+++ SRTMConGen.cpp	(working copy)
@@ -20,7 +20,10 @@
 #include "Map.h"
 #include "llgr.h"
 #include <cmath>
-#include <libshp/shapefil.h>
+#include <shapefil.h>
+#include <deque>
+#include <map>
+#include <set>
 
 using OSM::EarthPoint;
 
@@ -180,58 +183,261 @@
 	}
 }
 
-void SRTMConGen::generateShp (const char* shpname,int interval)
+
+typedef std::multimap<int,LINE> SegmentCache;
+typedef std::deque<LINE*> Contour;
+typedef std::set<int> Range;
+
+struct LineString
 {
-	SHPHandle shp = SHPCreate(shpname,SHPT_ARC);
-	DBFHandle dbf = DBFCreate(shpname);
-	int htidx = DBFAddField(dbf,"height",FTInteger,255,0);
-	int mjridx = DBFAddField(dbf,"major",FTInteger,255,0);
-	double xs[2], ys[2];
-	for(int row=0; row<sampledata->getHeight()-1; row++)
-	{
-		// Do each point of the current row
-		for(int col=0; col<sampledata->getWidth()-1; col++)
-		{
-			sampledata->setPoint (row,col);
-			int start_ht = sampledata->startHeight(interval),
-			end_ht = sampledata->endHeight(interval);
-			
+      typedef std::vector<double> List;
+      
+   public:
+      LineString(int height)
+         : height_(height),
+           length_(0)
+      {}
+      
+      ~LineString() {}
+      
+      void add_first(double x, double y)
+      {
+         if (xs_.size() > 0)
+         {
+            double dx = xs_[0]-x;
+            double dy = ys_[0]-y;
+            length_ += sqrt(dx*dx + dy*dy); 
+         }
+         xs_.insert(xs_.begin(),x);
+         ys_.insert(ys_.begin(),y);
+         
+      }
 
-			LINE lines[2];
-			int n_line_pts;
-			char htstr[1024];
+      void add_last(double x, double y)
+      {
+         unsigned size = xs_.size();
+         if ( size > 0)
+         {
+            double dx = xs_[size-1]-x;
+            double dy = ys_[size-1]-y;
+            length_ += sqrt(dx*dx + dy*dy); 
+         }
+         xs_.push_back(x);
+         ys_.push_back(y);
+      }
+      
+      unsigned size() const
+      {
+         return xs_.size();
+      }
 
-			for(int ht=start_ht; ht<=end_ht; ht+=interval)
-			{
-				n_line_pts=0;
-				sampledata->getLine(lines,&n_line_pts,ht,false);
+      int height() const
+      {
+         return height_;
+      }
 
+      unsigned length () const 
+      {
+         return length_;
+      }
 
-				// draw line
-				if(n_line_pts!=0)
-				{
-					for(int count=0; count<n_line_pts; count++)
-					{
-						xs[0] = lines[count].p[0].x;
-						xs[1] = lines[count].p[1].x;
-						ys[0] = lines[count].p[0].y;
-						ys[1] = lines[count].p[1].y;
+      double * xs ()
+      {
+         return &xs_[0];
+      }
+      double * ys ()
+      {
+         return &ys_[0];
+      }
+      int height_;
+      unsigned length_;
+      List xs_;
+      List ys_;
+};
 
-						SHPObject *object = SHPCreateSimpleObject
-							(SHPT_ARC,2,xs,ys,NULL);
-						int objid = SHPWriteObject(shp,-1,object);
-						SHPDestroyObject(object);
-						
-						DBFWriteIntegerAttribute (dbf,objid,htidx,ht);
-						DBFWriteIntegerAttribute (dbf,objid,mjridx,
-							( ht%(interval*5) == 0 ? 1:0));
-					}		
-				}
-			}
-		}
-	}
-	DBFClose(dbf);
-	SHPClose(shp);
+struct shape_writer 
+{
+      shape_writer(SHPHandle & shp, DBFHandle & dbf, int htidx, int mjridx, int interval)
+         : shp_(shp),
+           dbf_(dbf),
+           htidx_(htidx),
+           mjridx_(mjridx),
+           interval_(interval)
+      {}
+      
+      template <typename T>
+      void operator() (T) const;
+      
+      void operator() (LINE const& line)
+      {
+         //xs[0] = line.p[0].x;
+         //xs[1] = line.p[1].x;
+         //ys[0] = line.p[0].y;
+         //ys[1] = line.p[1].y;
+         
+         //SHPObject *object = SHPCreateSimpleObject(SHPT_ARC,2,xs,ys,0);
+         //int objid = SHPWriteObject(shp_,-1,object);
+         //SHPDestroyObject(object);
+         //DBFWriteIntegerAttribute (dbf_,objid,htidx_,segment.ht);
+         //DBFWriteIntegerAttribute (dbf_,objid,mjridx_,( segment.ht %(interval_*5) == 0 ? 1:0));
+      }
+      
+      void operator() (LineString & line)
+      {
+         std::cout << "writing LINE num points=" << line.size() << " lenghth=" << line.length() << "\n";
+         double * xs = line.xs();
+         double * ys = line.ys();
+         unsigned size = line.size();
+         SHPObject *object = SHPCreateSimpleObject(SHPT_ARC,size,xs,ys,0);
+         int objid = SHPWriteObject(shp_,-1,object);
+         SHPDestroyObject(object);
+         DBFWriteIntegerAttribute (dbf_,objid,htidx_,line.height());
+         DBFWriteIntegerAttribute (dbf_,objid,mjridx_,( line.height()  % ( interval_*5) == 0 ? 1:0));
+      }
+      
+      double xs[2];
+      double ys[2];
+      int htidx_;
+      int mjridx_;
+      int interval_;
+      SHPHandle & shp_;
+      DBFHandle & dbf_;
+      
+};
+
+void merge_segments (Contour & contour, LineString & line, unsigned maxlength)
+{
+   bool first = true;
+   unsigned max = contour.size()*contour.size();
+   unsigned i = 0;
+   double start_x;
+   double start_y;
+   double end_x;
+   double end_y;
+   
+   while (contour.size() && i++ < max)
+   {
+      LINE * seg = *(contour.end() - 1);
+      double x0 = seg->p[0].x;
+      double y0 = seg->p[0].y;
+      double x1 = seg->p[1].x;
+      double y1 = seg->p[1].y;
+      contour.pop_back();
+      
+      if (first)
+      {
+         first = false;
+         start_x = x0;
+         start_y = y0;
+         end_x = x1;
+         end_y = y1;
+         line.add_last(x0,y0);
+         line.add_last(x1,y1);
+      }
+      else if (start_x == x0 && start_y == y0)
+      {
+         start_x = x1;
+         start_y = y1;
+         line.add_first(x1,y1);
+      }
+      else if (start_x == x1 && start_y == y1)
+      {
+         start_x = x0;
+         start_y = y0;
+         line.add_first(x0,y0);
+      }
+      else if (end_x == x0 && end_y == y0)
+      {
+         end_x = x1;
+         end_y = y1;
+         line.add_last(x1,y1);
+      }
+      else if (end_x == x1 && end_y == y1)
+      {
+         end_x = x0;
+         end_y = y0;
+         line.add_last(x0,y0);
+      } 
+      else
+      {
+         contour.push_front(seg);
+      }
+      if (line.length() > maxlength) break;
+   }
+} 
+
+void SRTMConGen::generateShp (const char* shpname,int interval)
+{
+   SHPHandle shp = SHPCreate(shpname,SHPT_ARC);
+   DBFHandle dbf = DBFCreate(shpname);
+   int htidx = DBFAddField(dbf,"height",FTInteger,255,0);
+   int mjridx = DBFAddField(dbf,"major",FTInteger,255,0);
+   double xs[2], ys[2];
+   
+   SegmentCache segments;
+   Range heights;
+   for(int row=0; row<sampledata->getHeight()-1; row++)
+   {
+      // Do each point of the current row
+      for(int col=0; col<sampledata->getWidth()-1; col++)
+      {
+         sampledata->setPoint (row,col);
+         int start_ht = sampledata->startHeight(interval),
+            end_ht = sampledata->endHeight(interval);
+			
+
+         LINE lines[2];
+         int n_line_pts;
+         char htstr[1024];
+
+         for(int ht=start_ht; ht<=end_ht; ht+=interval)
+         {
+            n_line_pts=0;
+            sampledata->getLine(lines,&n_line_pts,ht,false);
+            // draw line
+            if(n_line_pts!=0)
+            {
+               for(int count=0; count<n_line_pts; count++)
+               {
+                  segments.insert(std::make_pair(ht,lines[count]));
+                  heights.insert(ht);
+               }		
+            }
+         }
+      }
+   }
+   
+   shape_writer writer(shp,dbf,htidx,mjridx,interval);
+   //std::for_each(segments.begin(),segments.end(),writer);
+   
+   Range::iterator itr = heights.begin();
+   Range::iterator end = heights.end();
+   
+   while (itr != end)
+   {
+      int height = *itr;
+      Contour contour;
+      SegmentCache::iterator pos;
+      
+      std::cout << "height = " <<  height << "\n";
+      for ( pos = segments.lower_bound(height);
+            pos != segments.upper_bound(height);
+            ++pos)
+      {
+         contour.push_back(&(pos->second));
+      }
+      
+      while (contour.size() > 0)
+      {
+         LineString line(height);
+         merge_segments(contour,line,1000);
+         writer(line);
+      }
+      ++itr;
+   }
+   
+   DBFClose(dbf);
+   SHPClose(shp);
 }
 
 void SRTMConGen::generateShading(DrawSurface *ds,double shadingres)
