Skip to content

Commit

Permalink
[pal] Cleanup and modernize code a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Mar 14, 2021
1 parent 0d5bbd3 commit 6102ecc
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 194 deletions.
12 changes: 7 additions & 5 deletions src/core/pal/feature.cpp
Expand Up @@ -104,7 +104,7 @@ void FeaturePart::extractCoords( const GEOSGeometry *geom )
hole->holeOf = nullptr;
// possibly not needed. it's not done for the exterior ring, so I'm not sure
// why it's just done here...
GeomFunction::reorderPolygon( hole->nbPoints, hole->x, hole->y );
GeomFunction::reorderPolygon( hole->x, hole->y );

mHoles << hole;
}
Expand Down Expand Up @@ -1629,18 +1629,20 @@ std::size_t FeaturePart::createCandidatesForPolygon( std::vector< std::unique_pt
const std::size_t targetPolygonCandidates = maxPolygonCandidates > 0 ? std::min( maxPolygonCandidates, static_cast< std::size_t>( std::ceil( mLF->layer()->mPal->maximumPolygonCandidatesPerMapUnitSquared() * area() ) ) )
: 0;

QLinkedList<PointSet *> shapes_toProcess;
QLinkedList<PointSet *> shapes_final;
const double totalArea = area();

mapShape->parent = nullptr;

if ( pal->isCanceled() )
return 0;

shapes_toProcess.append( mapShape );
QLinkedList<PointSet *> shapes_final = splitPolygons( mapShape, labelWidth, labelHeight );
QgsDebugMsg( QStringLiteral( "PAL split polygons resulted in:" ) );
for ( PointSet *ps : shapes_final )
{
QgsDebugMsg( ps->toWkt() );
}

splitPolygons( shapes_toProcess, shapes_final, labelWidth, labelHeight );

std::size_t nbp = 0;

Expand Down
142 changes: 62 additions & 80 deletions src/core/pal/geomfunction.cpp
Expand Up @@ -37,9 +37,12 @@

using namespace pal;

void heapsort( int *sid, int *id, const std::vector< double > &x, int N )
void heapsort( std::vector< int > &sid, int *id, const std::vector< double > &x, std::size_t N )
{
unsigned int n = N, i = n / 2, parent, child;
std::size_t n = N;
std::size_t i = n / 2;
std::size_t parent;
std::size_t child;
int tx;
for ( ;; )
{
Expand Down Expand Up @@ -79,9 +82,12 @@ void heapsort( int *sid, int *id, const std::vector< double > &x, int N )
}


void heapsort2( int *x, double *heap, int N )
void heapsort2( int *x, double *heap, std::size_t N )
{
unsigned int n = N, i = n / 2, parent, child;
std::size_t n = N;
std::size_t i = n / 2;
std::size_t parent;
std::size_t child;
double t;
int tx;
for ( ;; )
Expand Down Expand Up @@ -163,79 +169,73 @@ bool GeomFunction::computeLineIntersection( double x1, double y1, double x2, dou
return true;
}

int GeomFunction::convexHullId( int *id, const std::vector< double > &x, const std::vector< double > &y, int n, int *&cHull )
std::vector< int > GeomFunction::convexHullId( std::vector< int > &id, const std::vector< double > &x, const std::vector< double > &y )
{
int i;

cHull = new int[n];
for ( i = 0; i < n; i++ )
std::vector< int > convexHull( x.size() );
for ( std::size_t i = 0; i < x.size(); i++ )
{
cHull[i] = i;
convexHull[i] = static_cast< int >( i );
}

if ( x.size() <= 3 )
return convexHull;

if ( n <= 3 ) return n;

int *stack = new int[n];
double *tan = new double [n];
int ref;

int second, top;
double result;
std::vector< int > stack( x.size() );
std::vector< double > tan( x.size() );

// find the lowest y value
heapsort( cHull, id, y, n );
heapsort( convexHull, id.data(), y, y.size() );

// find the lowest x value from the lowest y
ref = 1;
while ( ref < n && qgsDoubleNear( y[id[cHull[ref]]], y[id[cHull[0]]] ) ) ref++;
std::size_t ref = 1;
while ( ref < x.size() && qgsDoubleNear( y[id[convexHull[ref]]], y[id[convexHull[0]]] ) )
ref++;

heapsort( cHull, id, x, ref );
heapsort( convexHull, id.data(), x, ref );

// the first point is now for sure in the hull as well as the ref one
for ( i = ref; i < n; i++ )
for ( std::size_t i = ref; i < x.size(); i++ )
{
if ( qgsDoubleNear( y[id[cHull[i]]], y[id[cHull[0]]] ) )
if ( qgsDoubleNear( y[id[convexHull[i]]], y[id[convexHull[0]]] ) )
tan[i] = FLT_MAX;
else
tan[i] = ( x[id[cHull[0]]] - x[id[cHull[i]]] ) / ( y[id[cHull[i]]] - y[id[cHull[0]]] );
tan[i] = ( x[id[convexHull[0]]] - x[id[convexHull[i]]] ) / ( y[id[convexHull[i]]] - y[id[convexHull[0]]] );
}

if ( ref < n )
heapsort2( cHull + ref, tan + ref, n - ref );
if ( ref < x.size() )
heapsort2( convexHull.data() + ref, tan.data() + ref, x.size() - ref );

// the second point is in too
stack[0] = cHull[0];
stack[0] = convexHull[0];
if ( ref == 1 )
{
stack[1] = cHull[1];
stack[1] = convexHull[1];
ref++;
}
else
stack[1] = cHull[ref - 1];
stack[1] = convexHull[ref - 1];

std::size_t top = 1;
std::size_t second = 0;

top = 1;
second = 0;

for ( i = ref; i < n; i++ )
for ( std::size_t i = ref; i < x.size(); i++ )
{
result = cross_product( x[id[stack[second]]], y[id[stack[second]]],
x[id[stack[top]]], y[id[stack[top]]], x[id[cHull[i]]], y[id[cHull[i]]] );
double result = cross_product( x[id[stack[second]]], y[id[stack[second]]],
x[id[stack[top]]], y[id[stack[top]]], x[id[convexHull[i]]], y[id[convexHull[i]]] );
// Coolineaire !! garder le plus éloigné
if ( qgsDoubleNear( result, 0.0 ) )
{
if ( dist_euc2d_sq( x[id[stack[second]]], y[id[stack[second]]], x[id[cHull[i]]], y[id[cHull[i]]] )
if ( dist_euc2d_sq( x[id[stack[second]]], y[id[stack[second]]], x[id[convexHull[i]]], y[id[convexHull[i]]] )
> dist_euc2d_sq( x[id[stack[second]]], y[id[stack[second]]], x[id[stack[top]]], y[id[stack[top]]] ) )
{
stack[top] = cHull[i];
stack[top] = convexHull[i];
}
}
else if ( result > 0 ) //convexe
{
second++;
top++;
stack[top] = cHull[i];
stack[top] = convexHull[i];
}
else
{
Expand All @@ -245,77 +245,59 @@ int GeomFunction::convexHullId( int *id, const std::vector< double > &x, const s
top--;
result = cross_product( x[id[stack[second]]],
y[id[stack[second]]], x[id[stack[top]]],
y[id[stack[top]]], x[id[cHull[i]]], y[id[cHull[i]]] );
y[id[stack[top]]], x[id[convexHull[i]]], y[id[convexHull[i]]] );
}
second++;
top++;
stack[top] = cHull[i];
stack[top] = convexHull[i];
}
}

for ( i = 0; i <= top; i++ )
for ( std::size_t i = 0; i <= top; i++ )
{
cHull[i] = stack[i];
convexHull[i] = stack[i];
}

delete[] stack;
delete[] tan;

return top + 1;
convexHull.resize( top + 1 );
return convexHull;
}

int GeomFunction::reorderPolygon( int nbPoints, std::vector<double> &x, std::vector<double> &y )
bool GeomFunction::reorderPolygon( std::vector<double> &x, std::vector<double> &y )
{
int inc = 0;
int *cHull = nullptr;
int i;
std::vector< int > pts( x.size() );
for ( std::size_t i = 0; i < x.size(); i++ )
pts[i] = static_cast< int >( i );

int *pts = new int[nbPoints];
for ( i = 0; i < nbPoints; i++ )
pts[i] = i;
std::vector< int > convexHull = convexHullId( pts, x, y );

( void )convexHullId( pts, x, y, nbPoints, cHull );

if ( pts[cHull[0]] < pts[cHull[1]] && pts[cHull[1]] < pts[cHull[2]] )
int inc = 0;
if ( pts[convexHull[0]] < pts[convexHull[1]] && pts[convexHull[1]] < pts[convexHull[2]] )
inc = 1;
else if ( pts[cHull[0]] > pts[cHull[1]] && pts[cHull[1]] > pts[cHull[2]] )
else if ( pts[convexHull[0]] > pts[convexHull[1]] && pts[convexHull[1]] > pts[convexHull[2]] )
inc = -1;
else if ( pts[cHull[0]] > pts[cHull[1]] && pts[cHull[1]] < pts[cHull[2]] && pts[cHull[2]] < pts[cHull[0]] )
else if ( pts[convexHull[0]] > pts[convexHull[1]] && pts[convexHull[1]] < pts[convexHull[2]] && pts[convexHull[2]] < pts[convexHull[0]] )
inc = 1;
else if ( pts[cHull[0]] > pts[cHull[1]] && pts[cHull[1]] < pts[cHull[2]] && pts[cHull[2]] > pts[cHull[0]] )
else if ( pts[convexHull[0]] > pts[convexHull[1]] && pts[convexHull[1]] < pts[convexHull[2]] && pts[convexHull[2]] > pts[convexHull[0]] )
inc = -1;
else if ( pts[cHull[0]] < pts[cHull[1]] && pts[cHull[1]] > pts[cHull[2]] && pts[cHull[2]] > pts[cHull[0]] )
else if ( pts[convexHull[0]] < pts[convexHull[1]] && pts[convexHull[1]] > pts[convexHull[2]] && pts[convexHull[2]] > pts[convexHull[0]] )
inc = -1;
else if ( pts[cHull[0]] < pts[cHull[1]] && pts[cHull[1]] > pts[cHull[2]] && pts[cHull[2]] < pts[cHull[0]] )
else if ( pts[convexHull[0]] < pts[convexHull[1]] && pts[convexHull[1]] > pts[convexHull[2]] && pts[convexHull[2]] < pts[convexHull[0]] )
inc = 1;
else
{
// wrong cHull
delete[] cHull;
delete[] pts;
return -1;
return false;
}

if ( inc == -1 ) // re-order points
{
double tmp;
int j;
for ( i = 0, j = nbPoints - 1; i <= j; i++, j-- )
for ( std::size_t i = 0, j = x.size() - 1; i <= j; i++, j-- )
{
tmp = x[i];
x[i] = x[j];
x[j] = tmp;

tmp = y[i];
y[i] = y[j];
y[j] = tmp;
std::swap( x[i], x[j] );
std::swap( y[i], y[j] );
}
}

delete[] cHull;
delete[] pts;

return 0;
return true;
}

bool GeomFunction::containsCandidate( const GEOSPreparedGeometry *geom, double x, double y, double width, double height, double alpha )
Expand Down
8 changes: 3 additions & 5 deletions src/core/pal/geomfunction.h
Expand Up @@ -83,11 +83,9 @@ namespace pal
* \param id set of point (i.e. point no 0 is (x,y) = x[id[0]],y[id[0]])
* \param x x coordinates
* \param y y coordinates
* \param n Size of subset (vector id)
* \param cHull returns the point id (id of id's vector...) whom are parts of the convex hull
* \returns convexHull's size
* \returns convexHull vertex ids
*/
static int convexHullId( int *id, const std::vector< double > &x, const std::vector< double > &y, int n, int *&cHull );
static std::vector< int > convexHullId( std::vector<int> &id, const std::vector< double > &x, const std::vector< double > &y );

/**
* Returns TRUE if the two segments intersect.
Expand All @@ -104,7 +102,7 @@ namespace pal
double *x, double *y );

//! Reorder points to have cross prod ((x,y)[i], (x,y)[i+1), point) > 0 when point is outside
static int reorderPolygon( int nbPoints, std::vector< double > &x, std::vector< double> &y );
static bool reorderPolygon( std::vector< double > &x, std::vector< double> &y );

/**
* Returns TRUE if a GEOS prepared geometry totally contains a label candidate.
Expand Down
4 changes: 2 additions & 2 deletions src/core/pal/layer.cpp
Expand Up @@ -144,7 +144,7 @@ bool Layer::registerFeature( QgsLabelFeature *lf )
}

// polygons: reorder coordinates
if ( type == GEOS_POLYGON && GeomFunction::reorderPolygon( fpart->nbPoints, fpart->x, fpart->y ) != 0 )
if ( type == GEOS_POLYGON && !GeomFunction::reorderPolygon( fpart->x, fpart->y ) )
{
continue;
}
Expand Down Expand Up @@ -234,7 +234,7 @@ bool Layer::registerFeature( QgsLabelFeature *lf )
}

// polygons: reorder coordinates
if ( type == GEOS_POLYGON && GeomFunction::reorderPolygon( fpart->nbPoints, fpart->x, fpart->y ) != 0 )
if ( type == GEOS_POLYGON && !GeomFunction::reorderPolygon( fpart->x, fpart->y ) )
{
continue;
}
Expand Down

0 comments on commit 6102ecc

Please sign in to comment.