1
0
Fork 0

Fixes from full world parsing tests

- Use new SimGear API in construct to gather all tiles within a bounding box
- Bring in new clipper lib, which seems to fix more orientation issues
- Various debug cleanup
- Fix Find/Merge slivers - but leave it turned off
- New OffsetPoints for small speedup in GenApts - currently disabled
This commit is contained in:
Peter Sadrozinski 2013-03-10 09:42:07 -04:00
parent 0d0d1d36c9
commit 08f5c17221
14 changed files with 944 additions and 729 deletions

View file

@ -515,17 +515,20 @@ int LinearFeature::Finish( bool closed, unsigned int idx )
// first point on the mark - offset heading is 90deg
cur_outer = OffsetPointFirst( points.GetNode(j), points.GetNode(j+1), offset-width/2.0f );
cur_inner = OffsetPointFirst( points.GetNode(j), points.GetNode(j+1), offset+width/2.0f );
// OffsetPointsFirst( points.GetNode(j), points.GetNode(j+1), offset, width, cur_inner, cur_outer );
}
else if (j == marks[i]->end_idx)
{
// last point on the mark - offset heading is 90deg
cur_outer = OffsetPointLast( points.GetNode(j-1), points.GetNode(j), offset-width/2.0f );
cur_inner = OffsetPointLast( points.GetNode(j-1), points.GetNode(j), offset+width/2.0f );
// OffsetPointsLast( points.GetNode(j-1), points.GetNode(j), offset, width, cur_inner, cur_outer );
}
else
{
cur_outer = OffsetPointMiddle( points.GetNode(j-1), points.GetNode(j), points.GetNode(j+1), offset-width/2.0f );
cur_inner = OffsetPointMiddle( points.GetNode(j-1), points.GetNode(j), points.GetNode(j+1), offset+width/2.0f );
// OffsetPointsMiddle( points.GetNode(j-1), points.GetNode(j), points.GetNode(j+1), offset, width, cur_inner, cur_outer );
}
if ( markStarted )

View file

@ -37,19 +37,5 @@ target_link_libraries(tg-construct
install(TARGETS tg-construct RUNTIME DESTINATION bin)
add_executable(cliptst
cliptst.cxx)
target_link_libraries(cliptst
terragear
${GDAL_LIBRARY}
${SIMGEAR_CORE_LIBRARIES}
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
)
install(TARGETS cliptst RUNTIME DESTINATION bin)
INSTALL(FILES usgsmap.txt DESTINATION ${PKGDATADIR} )
INSTALL(FILES default_priorities.txt DESTINATION ${PKGDATADIR} )

View file

@ -166,8 +166,9 @@ int main(int argc, char **argv) {
exit( -1 );
}
// three identical work queues
SGLockedQueue<SGBucket> wq[3];
// tile work queue
std::vector<SGBucket> bucketList;
SGLockedQueue<SGBucket> wq;
// First generate the workqueue of buckets to construct
if (tile_id == -1) {
@ -178,39 +179,27 @@ int main(int argc, char **argv) {
SGBucket b_max( max );
if ( b_min == b_max ) {
for (unsigned int q=0; q<3; q++) {
wq[q].push( b_min );
}
bucketList.push_back( b_min );
} else {
int dx, dy;
int i, j;
sgBucketDiff(b_min, b_max, &dx, &dy);
SG_LOG(SG_GENERAL, SG_ALERT, " construction area spans tile boundaries");
SG_LOG(SG_GENERAL, SG_ALERT, " dx = " << dx << " dy = " << dy);
for ( j = 0; j <= dy; j++ ) {
for ( i = 0; i <= dx; i++ ) {
for (unsigned int q=0; q<3; q++) {
wq[q].push( sgBucketOffset(min.getLongitudeDeg(), min.getLatitudeDeg(), i, j) );
}
}
}
sgGetBuckets( min, max, bucketList );
}
} else {
// construct the specified tile
SG_LOG(SG_GENERAL, SG_ALERT, "Building tile " << tile_id);
for (unsigned int q=0; q<3; q++) {
wq[q].push( SGBucket( tile_id ) );
}
bucketList.push_back( SGBucket( tile_id ) );
}
/* fill the workqueue */
for (unsigned int i=0; i<bucketList.size(); i++) {
wq.push( bucketList[i] );
}
// now create the worker threads for stage 1
std::vector<TGConstruct *> constructs;
for (int i=0; i<num_threads; i++) {
TGConstruct* construct = new TGConstruct( areas, 1, wq[0] );
TGConstruct* construct = new TGConstruct( areas, 1, wq );
//construct->set_cover( cover );
construct->set_paths( work_dir, share_dir, output_dir, load_dirs );
construct->set_options( ignoreLandmass, nudge );
@ -223,7 +212,7 @@ int main(int argc, char **argv) {
constructs[i]->start();
}
// wait for workqueue to empty
while( wq[0].size() ) {
while( wq.size() ) {
tgSleep( 5 );
}
// wait for all threads to complete
@ -237,8 +226,13 @@ int main(int argc, char **argv) {
}
constructs.clear();
/* fill the workqueue */
for (unsigned int i=0; i<bucketList.size(); i++) {
wq.push( bucketList[i] );
}
for (int i=0; i<num_threads; i++) {
TGConstruct* construct = new TGConstruct( areas, 2, wq[1] );
TGConstruct* construct = new TGConstruct( areas, 2, wq );
//construct->set_cover( cover );
construct->set_paths( work_dir, share_dir, output_dir, load_dirs );
construct->set_options( ignoreLandmass, nudge );
@ -251,7 +245,7 @@ int main(int argc, char **argv) {
constructs[i]->start();
}
// wait for workqueue to empty
while( wq[1].size() ) {
while( wq.size() ) {
tgSleep( 5 );
}
// wait for all threads to complete
@ -264,8 +258,13 @@ int main(int argc, char **argv) {
}
constructs.clear();
/* fill the workqueue */
for (unsigned int i=0; i<bucketList.size(); i++) {
wq.push( bucketList[i] );
}
for (int i=0; i<num_threads; i++) {
TGConstruct* construct = new TGConstruct( areas, 3, wq[2] );
TGConstruct* construct = new TGConstruct( areas, 3, wq );
//construct->set_cover( cover );
construct->set_paths( work_dir, share_dir, output_dir, load_dirs );
construct->set_options( ignoreLandmass, nudge );
@ -278,7 +277,7 @@ int main(int argc, char **argv) {
constructs[i]->start();
}
// wait for workqueue to empty
while( wq[2].size() ) {
while( wq.size() ) {
tgSleep( 5 );
}
// wait for all threads to complete

View file

@ -198,7 +198,10 @@ bool TGConstruct::ClipLandclassPolys( void ) {
#if FIND_SLIVERS
// Now, merge any slivers with clipped polys
merge_slivers(polys_clipped, slivers);
// merge_slivers(polys_clipped, slivers);
for ( unsigned int i = 0; i < area_defs.size(); i++ ) {
tgPolygon::MergeSlivers( polys_clipped.get_polys(i), slivers );
}
#endif
slivers.clear();
@ -224,7 +227,9 @@ bool TGConstruct::ClipLandclassPolys( void ) {
}
}
merge_slivers(polys_clipped, slivers);
for ( unsigned int i = 0; i < area_defs.size(); i++ ) {
tgPolygon::MergeSlivers( polys_clipped.get_polys(i), slivers );
}
}
#endif
@ -253,4 +258,4 @@ bool TGConstruct::ClipLandclassPolys( void ) {
}
return true;
}
}

View file

@ -29,6 +29,8 @@
#include <simgear/misc/sg_dir.hxx>
#include <simgear/debug/logstream.hxx>
#include <terragear/tg_shapefile.hxx>
#include "tgconstruct.hxx"
using std::string;
@ -103,6 +105,13 @@ int TGConstruct::LoadLandclassPolys( void ) {
}
}
}
if (IsDebugShape( poly.GetId() )) {
char layer[32];
sprintf(layer, "loaded_%d", poly.GetId() );
tgShapefile::FromPolygon( poly, ds_name, layer, material.c_str() );
}
}
gzclose( fp );

View file

@ -42,7 +42,9 @@ void TGConstruct::TesselatePolys( void )
tgPolygon poly = polys_clipped.get_poly(area, p );
if ( IsDebugShape( poly.GetId() ) ) {
tgShapefile::FromPolygon( poly, ds_name, "preteselate", "" );
char pn[32];
sprintf(pn, "%d", poly.GetId() );
tgShapefile::FromPolygon( poly, ds_name, "preteselate", pn );
}
tgRectangle rect = poly.GetBoundingBox();

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,10 @@
/*******************************************************************************
* *
* Author : Angus Johnson *
* Version : 4.9.1 *
* Date : 9 October 2012 *
* Version : 5.1.2 *
* Date : 25 February 2013 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2012 *
* Copyright : Angus Johnson 2010-2013 *
* *
* License: *
* Use, modification & distribution is subject to Boost Software License Ver 1. *
@ -26,7 +26,7 @@
* Paper no. DETC2005-85513 pp. 565-575 *
* ASME 2005 International Design Engineering Technical Conferences *
* and Computers and Information in Engineering Conference (IDETC/CIE2005) *
* September 2428, 2005 , Long Beach, California, USA *
* September 24-28, 2005 , Long Beach, California, USA *
* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
* *
*******************************************************************************/
@ -64,30 +64,64 @@ public:
typedef std::vector< IntPoint > Polygon;
typedef std::vector< Polygon > Polygons;
std::ostream& operator <<(std::ostream &s, Polygon &p);
std::ostream& operator <<(std::ostream &s, Polygons &p);
struct ExPolygon {
Polygon outer;
Polygons holes;
};
typedef std::vector< ExPolygon > ExPolygons;
class PolyNode;
typedef std::vector< PolyNode* > PolyNodes;
class PolyNode
{
public:
PolyNode();
Polygon Contour;
PolyNodes Childs;
PolyNode* Parent;
PolyNode* GetNext() const;
bool IsHole() const;
int ChildCount() const;
private:
PolyNode* GetNextSiblingUp() const;
unsigned Index; //node index in Parent.Childs
void AddChild(PolyNode& child);
friend class Clipper; //to access Index
};
class PolyTree: public PolyNode
{
public:
~PolyTree(){Clear();};
PolyNode* GetFirst() const;
void Clear();
int Total() const;
private:
PolyNodes AllNodes;
friend class Clipper; //to access AllNodes
};
enum JoinType { jtSquare, jtRound, jtMiter };
bool Orientation(const Polygon &poly);
double Area(const Polygon &poly);
void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys,
double delta, JoinType jointype = jtSquare, double MiterLimit = 2);
double delta, JoinType jointype = jtSquare, double limit = 0, bool autoFix = true);
void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
void SimplifyPolygons(Polygons &polys, PolyFillType fillType = pftEvenOdd);
void CleanPolygon(Polygon& in_poly, Polygon& out_poly, double distance = 1.415);
void CleanPolygons(Polygons& in_polys, Polygons& out_polys, double distance = 1.415);
void PolyTreeToPolygons(PolyTree& polytree, Polygons& polygons);
void ReversePolygon(Polygon& p);
void ReversePolygons(Polygons& p);
//used internally ...
enum EdgeSide { esNeither = 0, esLeft = 1, esRight = 2, esBoth = 3 };
enum EdgeSide { esLeft = 1, esRight = 2};
enum IntersectProtects { ipNone = 0, ipLeft = 1, ipRight = 2, ipBoth = 3 };
struct TEdge {
@ -140,12 +174,10 @@ struct OutPt; //forward declaration
struct OutRec {
int idx;
bool isHole;
OutRec *FirstLeft;
OutRec *AppendLink;
OutRec *FirstLeft; //see comments in clipper.pas
PolyNode *polyNode;
OutPt *pts;
OutPt *bottomPt;
OutPt *bottomFlag;
EdgeSide sides;
};
struct OutPt {
@ -206,19 +238,19 @@ public:
Clipper();
~Clipper();
bool Execute(ClipType clipType,
Polygons &solution,
PolyFillType subjFillType = pftEvenOdd,
PolyFillType clipFillType = pftEvenOdd);
Polygons &solution,
PolyFillType subjFillType = pftEvenOdd,
PolyFillType clipFillType = pftEvenOdd);
bool Execute(ClipType clipType,
ExPolygons &solution,
PolyFillType subjFillType = pftEvenOdd,
PolyFillType clipFillType = pftEvenOdd);
PolyTree &polytree,
PolyFillType subjFillType = pftEvenOdd,
PolyFillType clipFillType = pftEvenOdd);
void Clear();
bool ReverseSolution() {return m_ReverseOutput;};
void ReverseSolution(bool value) {m_ReverseOutput = value;};
protected:
void Reset();
virtual bool ExecuteInternal(bool fixHoleLinkages);
virtual bool ExecuteInternal();
private:
PolyOutList m_PolyOuts;
JoinList m_Joins;
@ -227,11 +259,12 @@ private:
Scanbeam *m_Scanbeam;
TEdge *m_ActiveEdges;
TEdge *m_SortedEdges;
IntersectNode *m_IntersectNodes;
bool m_ExecuteLocked;
PolyFillType m_ClipFillType;
PolyFillType m_SubjFillType;
bool m_ReverseOutput;
IntersectNode *m_IntersectNodes;
bool m_ExecuteLocked;
PolyFillType m_ClipFillType;
PolyFillType m_SubjFillType;
bool m_ReverseOutput;
bool m_UsingPolyTree;
void DisposeScanbeamList();
void SetWindingCount(TEdge& edge);
bool IsEvenOddFillType(const TEdge& edge) const;
@ -259,10 +292,9 @@ private:
void DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt);
void DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt);
void IntersectEdges(TEdge *e1, TEdge *e2,
const IntPoint &pt, IntersectProtects protects);
const IntPoint &pt, const IntersectProtects protects);
OutRec* CreateOutRec();
void AddOutPt(TEdge *e, const IntPoint &pt);
void DisposeBottomPt(OutRec &outRec);
void DisposeAllPolyPts();
void DisposeOutRec(PolyOutList::size_type index);
bool ProcessIntersections(const long64 botY, const long64 topY);
@ -271,18 +303,22 @@ private:
void ProcessIntersectList();
void ProcessEdgesAtTopOfScanbeam(const long64 topY);
void BuildResult(Polygons& polys);
void BuildResultEx(ExPolygons& polys);
void BuildResult2(PolyTree& polytree);
void SetHoleState(TEdge *e, OutRec *OutRec);
void DisposeIntersectNodes();
bool FixupIntersections();
bool FixupIntersectionOrder();
void FixupOutPolygon(OutRec &outRec);
bool IsHole(TEdge *e);
void FixHoleLinkage(OutRec *outRec);
void FixHoleLinkage(OutRec &outRec);
void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1);
void ClearJoins();
void AddHorzJoin(TEdge *e, int idx);
void ClearHorzJoins();
void JoinCommonEdges(bool fixHoleLinkages);
bool JoinPoints(const JoinRec *j, OutPt *&p1, OutPt *&p2);
void FixupJoinRecs(JoinRec *j, OutPt *pt, unsigned startIdx);
void JoinCommonEdges();
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec);
};
//------------------------------------------------------------------------------

View file

@ -61,8 +61,8 @@ void tgAccumulator::Add( const tgContour& subject )
void tgAccumulator::ToShapefiles( const std::string& path, const std::string& layer_prefix, bool individual )
{
char shapefile[16];
char layer[16];
char shapefile[32];
char layer[32];
if ( individual ) {
for (unsigned int i=0; i < accum.size(); i++) {

View file

@ -194,6 +194,7 @@ SGGeod OffsetPointMiddle( const SGGeod& gPrev, const SGGeod& gCur, const SGGeod&
return OffsetPointMiddle( gPrev, gCur, gNext, offset_by, unused );
}
SGGeod OffsetPointFirst( const SGGeod& cur, const SGGeod& next, double offset_by )
{
double courseOffset;
@ -232,6 +233,106 @@ SGGeod OffsetPointLast( const SGGeod& prev, const SGGeod& cur, double offset_by
return pt;
}
void OffsetPointsMiddle( const SGGeod& gPrev, const SGGeod& gCur, const SGGeod& gNext, double offset_by, double width, int& turn_dir, SGGeod& inner, SGGeod& outer )
{
double courseCur, courseNext, courseAvg, theta;
SGVec3d dirCur, dirNext, dirAvg, cp;
double courseOffset, distOffsetInner, distOffsetOuter;
SGGeod pt;
SG_LOG(SG_GENERAL, SG_DEBUG, "Find average angle for contour: prev (" << gPrev << "), "
"cur (" << gCur << "), "
"next (" << gNext << ")" );
// 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
courseCur = SGGeodesy::courseDeg( gCur, gPrev );
dirCur = SGVec3d( sin( courseCur*SGD_DEGREES_TO_RADIANS ), cos( courseCur*SGD_DEGREES_TO_RADIANS ), 0.0f );
courseNext = SGGeodesy::courseDeg( gCur, gNext );
dirNext = SGVec3d( sin( courseNext*SGD_DEGREES_TO_RADIANS ), cos( courseNext*SGD_DEGREES_TO_RADIANS ), 0.0f );
// Now find the average
dirAvg = normalize( dirCur + dirNext );
courseAvg = SGMiscd::rad2deg( atan( dirAvg.x()/dirAvg.y() ) );
if (courseAvg < 0) {
courseAvg += 180.0f;
}
// check the turn direction
cp = cross( dirCur, dirNext );
theta = SGMiscd::rad2deg(CalculateTheta( dirCur, dirNext ) );
if ( (abs(theta - 180.0) < 0.1) || (abs(theta) < 0.1) || (isnan(theta)) ) {
// straight line blows up math - offset 90 degree and dist is as given
courseOffset = SGMiscd::normalizePeriodic(0, 360, courseNext-90.0);
distOffsetInner = offset_by+width/2.0f;
distOffsetOuter = offset_by-width/2.0f;
} else {
// calculate correct distance for the offset point
if (cp.z() < 0.0f) {
courseOffset = SGMiscd::normalizePeriodic(0, 360, courseAvg+180);
turn_dir = 0;
} else {
courseOffset = SGMiscd::normalizePeriodic(0, 360, courseAvg);
turn_dir = 1;
}
distOffsetInner = (offset_by+width/2.0f)/sin(SGMiscd::deg2rad(courseNext-courseOffset));
distOffsetOuter = (offset_by-width/2.0f)/sin(SGMiscd::deg2rad(courseNext-courseOffset));
}
// calculate the points from cur
inner = SGGeodesy::direct(gCur, courseOffset, distOffsetInner);
outer = SGGeodesy::direct(gCur, courseOffset, distOffsetOuter);
}
void OffsetPointsMiddle( const SGGeod& gPrev, const SGGeod& gCur, const SGGeod& gNext, double offset_by, double width, SGGeod& inner, SGGeod& outer )
{
int unused;
return OffsetPointsMiddle( gPrev, gCur, gNext, offset_by, width, unused, inner, outer );
}
void OffsetPointsFirst( const SGGeod& cur, const SGGeod& next, double offset_by, double width, SGGeod& inner, SGGeod& outer )
{
double courseOffset;
SG_LOG(SG_GENERAL, SG_DEBUG, "Find OffsetPoint at Start : cur (" << cur << "), "
"next (" << next << ")" );
// find the offset angle
courseOffset = SGGeodesy::courseDeg( cur, next ) - 90;
courseOffset = SGMiscd::normalizePeriodic(0, 360, courseOffset);
// calculate the point from cur
inner = SGGeodesy::direct( cur, courseOffset, offset_by+width/2.0f );
outer = SGGeodesy::direct( cur, courseOffset, offset_by-width/2.0f );
}
void OffsetPointsLast( const SGGeod& prev, const SGGeod& cur, double offset_by, double width, SGGeod& inner, SGGeod& outer )
{
double courseOffset;
SG_LOG(SG_GENERAL, SG_DEBUG, "Find OffsetPoint at End : prev (" << prev << "), "
"cur (" << cur << ")" );
// find the offset angle
courseOffset = SGGeodesy::courseDeg( prev, cur ) - 90;
courseOffset = SGMiscd::normalizePeriodic(0, 360, courseOffset);
// calculate the point from cur
inner = SGGeodesy::direct( cur, courseOffset, offset_by+width/2.0f );
outer = SGGeodesy::direct( cur, courseOffset, offset_by-width/2.0f );
}
SGGeod midpoint( const SGGeod& p0, const SGGeod& p1 )
{
return SGGeod::fromDegM( (p0.getLongitudeDeg() + p1.getLongitudeDeg()) / 2,

View file

@ -71,6 +71,11 @@ SGGeod OffsetPointMiddle( const SGGeod& gPrev, const SGGeod& gCur, const SGGeod&
SGGeod OffsetPointFirst( const SGGeod& cur, const SGGeod& next, double offset_by );
SGGeod OffsetPointLast( const SGGeod& prev, const SGGeod& cur, double offset_by );
void OffsetPointsMiddle( const SGGeod& gPrev, const SGGeod& gCur, const SGGeod& gNext, double offset_by, double width, int& turn_dir, SGGeod& inner, SGGeod& outer );
void OffsetPointsMiddle( const SGGeod& gPrev, const SGGeod& gCur, const SGGeod& gNext, double offset_by, double width, SGGeod& inner, SGGeod& outer );
void OffsetPointsFirst( const SGGeod& cur, const SGGeod& next, double offset_by, double width, SGGeod& inner, SGGeod& outer );
void OffsetPointsLast( const SGGeod& prev, const SGGeod& cur, double offset_by, double width, SGGeod& inner, SGGeod& outer );
// what abount this?
// Save clipper to shapefile

View file

@ -174,7 +174,6 @@ tgPolygon tgPolygon::RemoveSpikes( const tgPolygon& subject )
// Move slivers from in polygon to out polygon.
void tgPolygon::RemoveSlivers( tgPolygon& subject, tgcontour_list& slivers )
{
#if 0
// traverse each contour of the polygon and attempt to identify
// likely slivers
SG_LOG(SG_GENERAL, SG_DEBUG, "tgPolygon::RemoveSlivers()");
@ -226,7 +225,6 @@ void tgPolygon::RemoveSlivers( tgPolygon& subject, tgcontour_list& slivers )
}
}
}
#endif
}
tgcontour_list tgPolygon::MergeSlivers( tgpolygon_list& polys, tgcontour_list& sliver_list ) {

View file

@ -128,6 +128,50 @@ void tgShapefile::FromClipper( const ClipperLib::Polygons& subject, const std::s
}
}
void tgShapefile::FromContour( const tgContour& subject, const std::string& datasource, const std::string& layer, const std::string& description )
{
void* ds_id = tgShapefile::OpenDatasource( datasource.c_str() );
SG_LOG(SG_GENERAL, SG_DEBUG, "tgShapefile::OpenDatasource returned " << (unsigned long)ds_id);
OGRLayer* l_id = (OGRLayer *)tgShapefile::OpenLayer( ds_id, layer.c_str() );
SG_LOG(SG_GENERAL, SG_DEBUG, "tgShapefile::OpenLayer returned " << (unsigned long)l_id);
OGRPolygon* polygon = new OGRPolygon();
if (subject.GetSize() < 3) {
SG_LOG(SG_GENERAL, SG_DEBUG, "Polygon with less than 3 points");
} else {
// FIXME: Current we ignore the hole-flag and instead assume
// that the first ring is not a hole and the rest
// are holes
OGRLinearRing *ring=new OGRLinearRing();
for (unsigned int pt = 0; pt < subject.GetSize(); pt++) {
OGRPoint *point=new OGRPoint();
point->setX( subject.GetNode(pt).getLongitudeDeg() );
point->setY( subject.GetNode(pt).getLatitudeDeg() );
point->setZ( 0.0 );
ring->addPoint(point);
}
ring->closeRings();
polygon->addRingDirectly(ring);
OGRFeature* feature = NULL;
feature = new OGRFeature( l_id->GetLayerDefn() );
feature->SetField("ID", description.c_str());
feature->SetGeometry(polygon);
if( l_id->CreateFeature( feature ) != OGRERR_NONE )
{
SG_LOG(SG_GENERAL, SG_ALERT, "Failed to create feature in shapefile");
}
OGRFeature::DestroyFeature(feature);
}
// close after each write
ds_id = tgShapefile::CloseDatasource( ds_id );
}
void tgShapefile::FromPolygon( const tgPolygon& subject, const std::string& datasource, const std::string& layer, const std::string& description )
{
void* ds_id = tgShapefile::OpenDatasource( datasource.c_str() );

View file

@ -6,6 +6,7 @@
class tgShapefile
{
public:
static void FromContour( const tgContour& subject, const std::string& datasource, const std::string& layer, const std::string& description );
static void FromPolygon( const tgPolygon& subject, const std::string& datasource, const std::string& layer, const std::string& description );
static tgPolygon ToPolygon( const void* subject );