Skip to content

Commit dd9b98a

Browse files
committed
[FEATURE]: geometry offset for event layer function
1 parent a0db1e3 commit dd9b98a

File tree

2 files changed

+174
-5
lines changed

2 files changed

+174
-5
lines changed

src/analysis/vector/qgsgeometryanalyzer.cpp

+171-3
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,7 @@ bool QgsGeometryAnalyzer::eventLayer( QgsVectorLayer* lineLayer, QgsVectorLayer*
10351035
return true;
10361036
}
10371037

1038-
void QgsGeometryAnalyzer::addEventLayerFeature( QgsFeature& feature, QgsGeometry* geom, const QgsGeometry* lineGeom, QgsVectorFileWriter* fileWriter, QgsFeatureList& memoryFeatures,
1038+
void QgsGeometryAnalyzer::addEventLayerFeature( QgsFeature& feature, QgsGeometry* geom, QgsGeometry* lineGeom, QgsVectorFileWriter* fileWriter, QgsFeatureList& memoryFeatures,
10391039
int offsetField, double offsetScale, bool forceSingleType )
10401040
{
10411041
if ( !geom )
@@ -1081,9 +1081,177 @@ void QgsGeometryAnalyzer::addEventLayerFeature( QgsFeature& feature, QgsGeometry
10811081
}
10821082
}
10831083

1084-
void QgsGeometryAnalyzer::createOffsetGeometry( QgsGeometry* geom, const QgsGeometry* lineGeom, double offset )
1084+
void QgsGeometryAnalyzer::createOffsetGeometry( QgsGeometry* geom, QgsGeometry* lineGeom, double offset )
10851085
{
1086-
//todo...
1086+
if( !geom || !lineGeom )
1087+
{
1088+
return;
1089+
}
1090+
1091+
QList<QgsGeometry*> inputGeomList;
1092+
1093+
if( geom->isMultipart() )
1094+
{
1095+
inputGeomList = geom->asGeometryCollection();
1096+
}
1097+
else
1098+
{
1099+
inputGeomList.push_back( geom );
1100+
}
1101+
1102+
QList<GEOSGeometry*> outputGeomList;
1103+
QList<QgsGeometry*>::const_iterator inputGeomIt = inputGeomList.constBegin();
1104+
for(; inputGeomIt != inputGeomList.constEnd(); ++inputGeomIt )
1105+
{
1106+
if( geom->type() == QGis::Line )
1107+
{
1108+
//geos 3.3 needed for line offsets
1109+
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
1110+
((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)))
1111+
outputGeomList.push_back( GEOSOffsetCurve( (*inputGeomIt)->asGeos(), offset, 8 /*quadSegments*/, 0 /*joinStyle*/, 5.0 /*mitreLimit*/ ) );
1112+
#else
1113+
outputGeomList.push_back( 0 );
1114+
#endif
1115+
}
1116+
else if( geom->type() == QGis::Point )
1117+
{
1118+
QgsPoint p = (*inputGeomIt)->asPoint();
1119+
p = createPointOffset( p.x(), p.y(), offset, lineGeom );
1120+
GEOSCoordSequence* ptSeq = GEOSCoordSeq_create( 1, 2 );
1121+
GEOSCoordSeq_setX( ptSeq, 0, p.x() );
1122+
GEOSCoordSeq_setY( ptSeq, 0, p.y() );
1123+
GEOSGeometry* geosPt = GEOSGeom_createPoint( ptSeq );
1124+
outputGeomList.push_back( geosPt );
1125+
}
1126+
}
1127+
1128+
if( !geom->isMultipart() )
1129+
{
1130+
GEOSGeometry* outputGeom = outputGeomList.at( 0 );
1131+
if( outputGeom )
1132+
{
1133+
geom->fromGeos( outputGeom );
1134+
}
1135+
}
1136+
else
1137+
{
1138+
GEOSGeometry** geomArray = new GEOSGeometry*[outputGeomList.size()];
1139+
for( int i = 0; i < outputGeomList.size(); ++i )
1140+
{
1141+
geomArray[i] = outputGeomList.at( i );
1142+
}
1143+
GEOSGeometry* collection = 0;
1144+
if( geom->type() == QGis::Point )
1145+
{
1146+
collection = GEOSGeom_createCollection( GEOS_MULTIPOINT, geomArray, outputGeomList.size() );
1147+
}
1148+
else if( geom->type() == QGis::Line )
1149+
{
1150+
collection = GEOSGeom_createCollection( GEOS_MULTILINESTRING, geomArray, outputGeomList.size() );
1151+
}
1152+
geom->fromGeos( collection );
1153+
delete[] geomArray;
1154+
}
1155+
}
1156+
1157+
#if 0
1158+
if( geom->type() == QGis::Line )
1159+
{
1160+
QList<GEOSGeometry*> outputGeomList;
1161+
QList<QgsGeometry*>::const_iterator inputGeomIt = inputGeomList.constBegin();
1162+
for(; inputGeomIt != inputGeomList.constEnd(); ++inputGeomIt )
1163+
{
1164+
//geos 3.3 needed for line offsets
1165+
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
1166+
((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)))
1167+
outputGeomList.push_back( GEOSOffsetCurve( (*inputGeomIt)->asGeos(), offset, 8 /*quadSegments*/, 0 /*joinStyle*/, 5.0 /*mitreLimit*/ ) );
1168+
#else
1169+
outputGeomList.push_back( 0 );
1170+
#endif
1171+
}
1172+
1173+
if( !geom->isMultipart() )
1174+
{
1175+
GEOSGeometry* outputGeom = outputGeomList.at( 0 );
1176+
if( outputGeom )
1177+
{
1178+
geom->fromGeos( outputGeom );
1179+
}
1180+
}
1181+
else
1182+
{
1183+
GEOSGeometry** geomArray = new GEOSGeometry*[outputGeomList.size()];
1184+
for( int i = 0; i < outputGeomList.size(); ++i )
1185+
{
1186+
geomArray[i] = outputGeomList.at( i );
1187+
}
1188+
GEOSGeometry* collection = GEOSGeom_createCollection( GEOS_MULTILINESTRING, geomArray, outputGeomList.size() );
1189+
geom->fromGeos( collection );
1190+
delete[] geomArray;
1191+
}
1192+
}
1193+
else if( geom->type() == QGis::Point )
1194+
{
1195+
QList<GEOSGeometry*> outputGeomList;
1196+
QList<QgsGeometry*>::const_iterator inputGeomIt = inputGeomList.constBegin();
1197+
for(; inputGeomIt != inputGeomList.constEnd(); ++inputGeomIt )
1198+
{
1199+
QgsPoint p = (*inputGeomIt)->asPoint();
1200+
p = createPointOffset( p.x(), p.y(), offset, lineGeom );
1201+
GEOSCoordSequence* ptSeq = GEOSCoordSeq_create( 1, 2 );
1202+
GEOSCoordSeq_setX( ptSeq, 0, p.x() );
1203+
GEOSCoordSeq_setY( ptSeq, 0, p.y() );
1204+
GEOSGeometry* geosPt = GEOSGeom_createPoint( ptSeq );
1205+
outputGeomList.push_back( geosPt );
1206+
//geom->fromGeos( geosPt );
1207+
}
1208+
1209+
if( !geom->isMultipart() )
1210+
{
1211+
GEOSGeometry* outputGeom = outputGeomList.at( 0 );
1212+
if( outputGeom )
1213+
{
1214+
geom->fromGeos( outputGeom );
1215+
}
1216+
}
1217+
else
1218+
{
1219+
GEOSGeometry** geomArray = new GEOSGeometry*[outputGeomList.size()];
1220+
for( int i = 0; i < outputGeomList.size(); ++i )
1221+
{
1222+
geomArray[i] = outputGeomList.at( i );
1223+
}
1224+
GEOSGeometry* collection = GEOSGeom_createCollection( GEOS_MULTIPOINT, geomArray, outputGeomList.size() );
1225+
geom->fromGeos( collection );
1226+
delete[] geomArray;
1227+
}
1228+
}
1229+
}
1230+
#endif //0
1231+
1232+
QgsPoint QgsGeometryAnalyzer::createPointOffset( double x, double y, double dist, QgsGeometry* lineGeom ) const
1233+
{
1234+
QgsPoint p( x, y );
1235+
QgsPoint minDistPoint;
1236+
int beforeVertexNr;
1237+
lineGeom->closestSegmentWithContext( p, minDistPoint, beforeVertexNr );
1238+
1239+
int afterVertexNr = beforeVertexNr + 1;
1240+
QgsPoint beforeVertex = lineGeom->vertexAt( beforeVertexNr );
1241+
QgsPoint afterVertex = lineGeom->vertexAt( afterVertexNr );
1242+
1243+
//get normal vector
1244+
double dx = afterVertex.x() - beforeVertex.x();
1245+
double dy = afterVertex.y() - beforeVertex.y();
1246+
double normalX = -dy;
1247+
double normalY = dx;
1248+
double normalLength = sqrt( normalX * normalX + normalY * normalY );
1249+
normalX *= ( dist / normalLength );
1250+
normalY *= ( dist / normalLength );
1251+
1252+
double debugLength = sqrt( normalX * normalX + normalY * normalY ); //control
1253+
1254+
return QgsPoint( x - normalX, y - normalY ); //negative values -> left side, positive values -> right side
10871255
}
10881256

10891257
QgsGeometry* QgsGeometryAnalyzer::locateBetweenMeasures( double fromMeasure, double toMeasure, QgsGeometry* lineGeom )

src/analysis/vector/qgsgeometryanalyzer.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,14 @@ class ANALYSIS_EXPORT QgsGeometryAnalyzer
142142
void dissolveFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry** dissolveGeometry );
143143

144144
//helper functions for event layer
145-
void addEventLayerFeature( QgsFeature& feature, QgsGeometry* geom, const QgsGeometry* lineGeom, QgsVectorFileWriter* fileWriter, QgsFeatureList& memoryFeatures, int offsetField = -1, double offsetScale = 1.0,
145+
void addEventLayerFeature( QgsFeature& feature, QgsGeometry* geom, QgsGeometry* lineGeom, QgsVectorFileWriter* fileWriter, QgsFeatureList& memoryFeatures, int offsetField = -1, double offsetScale = 1.0,
146146
bool forceSingleType = false );
147147
/**Create geometry offset relative to line geometry.
148148
@param geom the geometry to modify
149149
@param the line geometry to wich the feature is referenced
150150
@param offset the offset value in layer unit. Negativ value means offset towards left, positive value is offset to the right side*/
151-
void createOffsetGeometry( QgsGeometry* geom, const QgsGeometry* lineGeom, double offset );
151+
void createOffsetGeometry( QgsGeometry* geom, QgsGeometry* lineGeom, double offset );
152+
QgsPoint createPointOffset( double x, double y, double dist, QgsGeometry* lineGeom ) const;
152153
unsigned char* locateBetweenWkbString( unsigned char* ptr, QgsMultiPolyline& result, double fromMeasure, double toMeasure );
153154
unsigned char* locateAlongWkbString( unsigned char* ptr, QgsMultiPoint& result, double measure );
154155
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 );

0 commit comments

Comments
 (0)