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:
parent
0d0d1d36c9
commit
08f5c17221
14 changed files with 944 additions and 729 deletions
|
@ -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 )
|
||||
|
|
|
@ -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} )
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
@ -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 24–28, 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);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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() );
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue