Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FEATURE]: geometry offset for event layer function
  • Loading branch information
mhugent committed Mar 31, 2012
1 parent a0db1e3 commit dd9b98a
Show file tree
Hide file tree
Showing 2 changed files with 174 additions and 5 deletions.
174 changes: 171 additions & 3 deletions src/analysis/vector/qgsgeometryanalyzer.cpp
Expand Up @@ -1035,7 +1035,7 @@ bool QgsGeometryAnalyzer::eventLayer( QgsVectorLayer* lineLayer, QgsVectorLayer*
return true;
}

void QgsGeometryAnalyzer::addEventLayerFeature( QgsFeature& feature, QgsGeometry* geom, const QgsGeometry* lineGeom, QgsVectorFileWriter* fileWriter, QgsFeatureList& memoryFeatures,
void QgsGeometryAnalyzer::addEventLayerFeature( QgsFeature& feature, QgsGeometry* geom, QgsGeometry* lineGeom, QgsVectorFileWriter* fileWriter, QgsFeatureList& memoryFeatures,
int offsetField, double offsetScale, bool forceSingleType )
{
if ( !geom )
Expand Down Expand Up @@ -1081,9 +1081,177 @@ void QgsGeometryAnalyzer::addEventLayerFeature( QgsFeature& feature, QgsGeometry
}
}

void QgsGeometryAnalyzer::createOffsetGeometry( QgsGeometry* geom, const QgsGeometry* lineGeom, double offset )
void QgsGeometryAnalyzer::createOffsetGeometry( QgsGeometry* geom, QgsGeometry* lineGeom, double offset )
{
//todo...
if( !geom || !lineGeom )
{
return;
}

QList<QgsGeometry*> inputGeomList;

if( geom->isMultipart() )
{
inputGeomList = geom->asGeometryCollection();
}
else
{
inputGeomList.push_back( geom );
}

QList<GEOSGeometry*> outputGeomList;
QList<QgsGeometry*>::const_iterator inputGeomIt = inputGeomList.constBegin();
for(; inputGeomIt != inputGeomList.constEnd(); ++inputGeomIt )
{
if( geom->type() == QGis::Line )
{
//geos 3.3 needed for line offsets
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)))
outputGeomList.push_back( GEOSOffsetCurve( (*inputGeomIt)->asGeos(), offset, 8 /*quadSegments*/, 0 /*joinStyle*/, 5.0 /*mitreLimit*/ ) );
#else
outputGeomList.push_back( 0 );
#endif
}
else if( geom->type() == QGis::Point )
{
QgsPoint p = (*inputGeomIt)->asPoint();
p = createPointOffset( p.x(), p.y(), offset, lineGeom );
GEOSCoordSequence* ptSeq = GEOSCoordSeq_create( 1, 2 );
GEOSCoordSeq_setX( ptSeq, 0, p.x() );
GEOSCoordSeq_setY( ptSeq, 0, p.y() );
GEOSGeometry* geosPt = GEOSGeom_createPoint( ptSeq );
outputGeomList.push_back( geosPt );
}
}

if( !geom->isMultipart() )
{
GEOSGeometry* outputGeom = outputGeomList.at( 0 );
if( outputGeom )
{
geom->fromGeos( outputGeom );
}
}
else
{
GEOSGeometry** geomArray = new GEOSGeometry*[outputGeomList.size()];
for( int i = 0; i < outputGeomList.size(); ++i )
{
geomArray[i] = outputGeomList.at( i );
}
GEOSGeometry* collection = 0;
if( geom->type() == QGis::Point )
{
collection = GEOSGeom_createCollection( GEOS_MULTIPOINT, geomArray, outputGeomList.size() );
}
else if( geom->type() == QGis::Line )
{
collection = GEOSGeom_createCollection( GEOS_MULTILINESTRING, geomArray, outputGeomList.size() );
}
geom->fromGeos( collection );
delete[] geomArray;
}
}

#if 0
if( geom->type() == QGis::Line )
{
QList<GEOSGeometry*> outputGeomList;
QList<QgsGeometry*>::const_iterator inputGeomIt = inputGeomList.constBegin();
for(; inputGeomIt != inputGeomList.constEnd(); ++inputGeomIt )
{
//geos 3.3 needed for line offsets
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)))
outputGeomList.push_back( GEOSOffsetCurve( (*inputGeomIt)->asGeos(), offset, 8 /*quadSegments*/, 0 /*joinStyle*/, 5.0 /*mitreLimit*/ ) );
#else
outputGeomList.push_back( 0 );
#endif
}

if( !geom->isMultipart() )
{
GEOSGeometry* outputGeom = outputGeomList.at( 0 );
if( outputGeom )
{
geom->fromGeos( outputGeom );
}
}
else
{
GEOSGeometry** geomArray = new GEOSGeometry*[outputGeomList.size()];
for( int i = 0; i < outputGeomList.size(); ++i )
{
geomArray[i] = outputGeomList.at( i );
}
GEOSGeometry* collection = GEOSGeom_createCollection( GEOS_MULTILINESTRING, geomArray, outputGeomList.size() );
geom->fromGeos( collection );
delete[] geomArray;
}
}
else if( geom->type() == QGis::Point )
{
QList<GEOSGeometry*> outputGeomList;
QList<QgsGeometry*>::const_iterator inputGeomIt = inputGeomList.constBegin();
for(; inputGeomIt != inputGeomList.constEnd(); ++inputGeomIt )
{
QgsPoint p = (*inputGeomIt)->asPoint();
p = createPointOffset( p.x(), p.y(), offset, lineGeom );
GEOSCoordSequence* ptSeq = GEOSCoordSeq_create( 1, 2 );
GEOSCoordSeq_setX( ptSeq, 0, p.x() );
GEOSCoordSeq_setY( ptSeq, 0, p.y() );
GEOSGeometry* geosPt = GEOSGeom_createPoint( ptSeq );
outputGeomList.push_back( geosPt );
//geom->fromGeos( geosPt );
}

if( !geom->isMultipart() )
{
GEOSGeometry* outputGeom = outputGeomList.at( 0 );
if( outputGeom )
{
geom->fromGeos( outputGeom );
}
}
else
{
GEOSGeometry** geomArray = new GEOSGeometry*[outputGeomList.size()];
for( int i = 0; i < outputGeomList.size(); ++i )
{
geomArray[i] = outputGeomList.at( i );
}
GEOSGeometry* collection = GEOSGeom_createCollection( GEOS_MULTIPOINT, geomArray, outputGeomList.size() );
geom->fromGeos( collection );
delete[] geomArray;
}
}
}
#endif //0

QgsPoint QgsGeometryAnalyzer::createPointOffset( double x, double y, double dist, QgsGeometry* lineGeom ) const
{
QgsPoint p( x, y );
QgsPoint minDistPoint;
int beforeVertexNr;
lineGeom->closestSegmentWithContext( p, minDistPoint, beforeVertexNr );

int afterVertexNr = beforeVertexNr + 1;
QgsPoint beforeVertex = lineGeom->vertexAt( beforeVertexNr );
QgsPoint afterVertex = lineGeom->vertexAt( afterVertexNr );

//get normal vector
double dx = afterVertex.x() - beforeVertex.x();
double dy = afterVertex.y() - beforeVertex.y();
double normalX = -dy;
double normalY = dx;
double normalLength = sqrt( normalX * normalX + normalY * normalY );
normalX *= ( dist / normalLength );
normalY *= ( dist / normalLength );

double debugLength = sqrt( normalX * normalX + normalY * normalY ); //control

return QgsPoint( x - normalX, y - normalY ); //negative values -> left side, positive values -> right side
}

QgsGeometry* QgsGeometryAnalyzer::locateBetweenMeasures( double fromMeasure, double toMeasure, QgsGeometry* lineGeom )
Expand Down
5 changes: 3 additions & 2 deletions src/analysis/vector/qgsgeometryanalyzer.h
Expand Up @@ -142,13 +142,14 @@ class ANALYSIS_EXPORT QgsGeometryAnalyzer
void dissolveFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry** dissolveGeometry );

//helper functions for event layer
void addEventLayerFeature( QgsFeature& feature, QgsGeometry* geom, const QgsGeometry* lineGeom, QgsVectorFileWriter* fileWriter, QgsFeatureList& memoryFeatures, int offsetField = -1, double offsetScale = 1.0,
void addEventLayerFeature( QgsFeature& feature, QgsGeometry* geom, QgsGeometry* lineGeom, QgsVectorFileWriter* fileWriter, QgsFeatureList& memoryFeatures, int offsetField = -1, double offsetScale = 1.0,
bool forceSingleType = false );
/**Create geometry offset relative to line geometry.
@param geom the geometry to modify
@param the line geometry to wich the feature is referenced
@param offset the offset value in layer unit. Negativ value means offset towards left, positive value is offset to the right side*/
void createOffsetGeometry( QgsGeometry* geom, const QgsGeometry* lineGeom, double offset );
void createOffsetGeometry( QgsGeometry* geom, QgsGeometry* lineGeom, double offset );
QgsPoint createPointOffset( double x, double y, double dist, QgsGeometry* lineGeom ) const;
unsigned char* locateBetweenWkbString( unsigned char* ptr, QgsMultiPolyline& result, double fromMeasure, double toMeasure );
unsigned char* locateAlongWkbString( unsigned char* ptr, QgsMultiPoint& result, double measure );
static bool clipSegmentByRange( double x1, double y1, double m1, double x2, double y2, double m2, double range1, double range2, QgsPoint& pt1, QgsPoint& pt2, bool& secondPointClipped );
Expand Down

0 comments on commit dd9b98a

Please sign in to comment.