7 #include <QProgressDialog> 16 QgsVectorLayer* baselineLayer,
bool shareBaseline, QString baselineStrataId,
const QString& outputPointLayer,
17 const QString& outputLineLayer,
const QString& usedBaselineLayer,
double minTransectLength ): mStrataLayer( strataLayer ),
18 mStrataIdAttribute( strataIdAttribute ), mMinDistanceAttribute( minDistanceAttribute ), mNPointsAttribute( nPointsAttribute ), mBaselineLayer( baselineLayer ), mShareBaseline( shareBaseline ),
19 mBaselineStrataId( baselineStrataId ), mOutputPointLayer( outputPointLayer ), mOutputLineLayer( outputLineLayer ), mUsedBaselineLayer( usedBaselineLayer ),
20 mMinDistanceUnits( minDistUnits ), mMinTransectLength( minTransectLength )
25 : mStrataLayer( NULL )
26 , mBaselineLayer( NULL )
27 , mShareBaseline(
false )
28 , mMinDistanceUnits(
Meters )
29 , mMinTransectLength( 0.0 )
41 if ( !mStrataLayer || !mStrataLayer->
isValid() )
46 if ( !mBaselineLayer || !mBaselineLayer->
isValid() )
52 QVariant::Type stratumIdType = QVariant::Int;
53 if ( !mStrataIdAttribute.isEmpty() )
61 outputPointFields.
append(
QgsField(
"station_id", QVariant::Int ) );
62 outputPointFields.
append(
QgsField(
"stratum_id", stratumIdType ) );
63 outputPointFields.
append(
QgsField(
"station_code", QVariant::String ) );
64 outputPointFields.
append(
QgsField(
"start_lat", QVariant::Double ) );
65 outputPointFields.
append(
QgsField(
"start_long", QVariant::Double ) );
68 &( mStrataLayer->
crs() ) );
74 outputPointFields.
append(
QgsField(
"bearing", QVariant::Double ) );
76 &( mStrataLayer->
crs() ) );
83 usedBaselineFields.
append(
QgsField(
"stratum_id", stratumIdType ) );
86 &( mStrataLayer->
crs() ) );
93 QFileInfo outputPointInfo( mOutputPointLayer );
94 QString bufferClipLineOutput = outputPointInfo.absolutePath() +
"/out_buffer_clip_line.shp";
102 if ( mMinDistanceUnits ==
Meters )
115 mt_srand( QTime::currentTime().msec() );
122 int nTotalTransects = 0;
134 pd->setValue( nFeatures );
136 if ( pd && pd->wasCanceled() )
149 QVariant strataId = fet.
attribute( mStrataIdAttribute );
150 QgsGeometry* baselineGeom = findBaselineGeometry( strataId.isValid() ? strataId : -1 );
156 double minDistance = fet.
attribute( mMinDistanceAttribute ).toDouble();
157 double minDistanceLayerUnits = minDistance;
159 double bufferDist = minDistance;
162 bufferDist = minDistance / 111319.9;
163 minDistanceLayerUnits = bufferDist;
169 delete clippedBaseline;
172 QgsGeometry* bufferLineClipped = clipBufferLine( strataGeom, clippedBaseline, bufferDist );
173 if ( !bufferLineClipped )
175 delete clippedBaseline;
187 int nTransects = fet.
attribute( mNPointsAttribute ).toInt();
188 int nCreatedTransects = 0;
190 int nMaxIterations = nTransects * 50;
193 QMap< QgsFeatureId, QgsGeometry* > lineFeatureMap;
195 while ( nCreatedTransects < nTransects && nIterations < nMaxIterations )
205 QgsPoint latLongSamplePoint = toLatLongTransform.transform( sampleQgsPoint );
209 samplePointFeature.
setAttribute(
"id", nTotalTransects + 1 );
210 samplePointFeature.
setAttribute(
"station_id", nCreatedTransects + 1 );
211 samplePointFeature.
setAttribute(
"stratum_id", strataId );
212 samplePointFeature.
setAttribute(
"station_code", strataId.toString() +
"_" + QString::number( nCreatedTransects + 1 ) );
213 samplePointFeature.
setAttribute(
"start_lat", latLongSamplePoint.
y() );
214 samplePointFeature.
setAttribute(
"start_long", latLongSamplePoint.
x() );
226 double bearing = distanceArea.
bearing( sampleQgsPoint, minDistPoint ) /
M_PI * 180.0;
229 QgsPoint ptFarAway( sampleQgsPoint.
x() + ( minDistPoint.
x() - sampleQgsPoint.
x() ) * 1000000,
230 sampleQgsPoint.
y() + ( minDistPoint.
y() - sampleQgsPoint.
y() ) * 1000000 );
232 lineFarAway << sampleQgsPoint << ptFarAway;
235 if ( !lineClipStratum )
237 delete lineFarAwayGeom;
delete lineClipStratum;
242 if ( lineClipStratum->
distance( *samplePoint ) > 0.000001 )
244 delete lineFarAwayGeom;
delete lineClipStratum;
252 QgsGeometry* singleLine = closestMultilineElement( sampleQgsPoint, lineClipStratum );
255 delete lineClipStratum;
256 lineClipStratum = singleLine;
261 double transectLength = distanceArea.
measure( lineClipStratum );
262 if ( transectLength < mMinTransectLength )
264 delete lineFarAwayGeom;
delete lineClipStratum;
269 if ( otherTransectWithinDistance( lineClipStratum, minDistanceLayerUnits, minDistance, sIndex, lineFeatureMap, distanceArea ) )
271 delete lineFarAwayGeom;
delete lineClipStratum;
278 sampleLineFeature.
setAttribute(
"id", nTotalTransects + 1 );
279 sampleLineFeature.
setAttribute(
"station_id", nCreatedTransects + 1 );
280 sampleLineFeature.
setAttribute(
"stratum_id", strataId );
281 sampleLineFeature.
setAttribute(
"station_code", strataId.toString() +
"_" + QString::number( nCreatedTransects + 1 ) );
282 sampleLineFeature.
setAttribute(
"start_lat", latLongSamplePoint.
y() );
283 sampleLineFeature.
setAttribute(
"start_long", latLongSamplePoint.
x() );
285 outputLineWriter.
addFeature( sampleLineFeature );
289 outputPointWriter.
addFeature( samplePointFeature );
294 delete lineFarAwayGeom;
298 delete clippedBaseline;
301 bufferClipFeature.
setGeometry( bufferLineClipped );
303 bufferClipLineWriter.
addFeature( bufferClipFeature );
307 QMap< QgsFeatureId, QgsGeometry* >::iterator featureMapIt = lineFeatureMap.begin();
308 for ( ; featureMapIt != lineFeatureMap.end(); ++featureMapIt )
310 delete( featureMapIt.value() );
312 lineFeatureMap.clear();
326 QgsGeometry* QgsTransectSample::findBaselineGeometry( QVariant strataId )
328 if ( !mBaselineLayer )
338 if ( strataId == fet.
attribute( mBaselineStrataId ) || mShareBaseline )
346 bool QgsTransectSample::otherTransectWithinDistance(
QgsGeometry* geom,
double minDistLayerUnit,
double minDistance,
QgsSpatialIndex& sIndex,
347 const QMap< QgsFeatureId, QgsGeometry* >& lineFeatureMap,
QgsDistanceArea& da )
360 QList<QgsFeatureId> lineIdList = sIndex.
intersects( rect );
362 QList<QgsFeatureId>::const_iterator lineIdIt = lineIdList.constBegin();
363 for ( ; lineIdIt != lineIdList.constEnd(); ++lineIdIt )
365 const QMap< QgsFeatureId, QgsGeometry* >::const_iterator idMapIt = lineFeatureMap.find( *lineIdIt );
366 if ( idMapIt != lineFeatureMap.constEnd() )
370 closestSegmentPoints( *geom, *( idMapIt.value() ), dist, pt1, pt2 );
373 if ( dist < minDistance )
402 if ( pl1.size() < 2 || pl2.size() < 2 )
412 double p1x = p11.
x();
413 double p1y = p11.
y();
414 double v1x = p12.
x() - p11.
x();
415 double v1y = p12.
y() - p11.
y();
416 double p2x = p21.
x();
417 double p2y = p21.
y();
418 double v2x = p22.
x() - p21.
x();
419 double v2y = p22.
y() - p21.
y();
421 double denominatorU = v2x * v1y - v2y * v1x;
422 double denominatorT = v1x * v2y - v1y * v2x;
437 if ( d1 <= d2 && d1 <= d3 && d1 <= d4 )
439 dist = sqrt( d1 ); pt1 = p11; pt2 = minDistPoint1;
442 else if ( d2 <= d1 && d2 <= d3 && d2 <= d4 )
444 dist = sqrt( d2 ); pt1 = p12; pt2 = minDistPoint2;
447 else if ( d3 <= d1 && d3 <= d2 && d3 <= d4 )
449 dist = sqrt( d3 ); pt1 = p21; pt2 = minDistPoint3;
454 dist = sqrt( d4 ); pt1 = p21; pt2 = minDistPoint4;
459 double u = ( p1x * v1y - p1y * v1x - p2x * v1y + p2y * v1x ) / denominatorU;
460 double t = ( p2x * v2y - p2y * v2x - p1x * v2y + p1y * v2x ) / denominatorT;
462 if ( u >= 0 && u <= 1.0 && t >= 0 && t <= 1.0 )
465 pt1.
setX( p2x + u * v2x );
466 pt1.
setY( p2y + u * v2y );
492 if ( t >= 0.0 && t <= 1.0 )
497 if ( u >= 0.0 && u <= 1.0 )
503 dist = sqrt( pt1.
sqrDist( pt2 ) );
515 double minDist = DBL_MAX;
516 double currentDist = 0;
522 QgsMultiPolyline::const_iterator it = multiPolyline.constBegin();
523 for ( ; it != multiPolyline.constEnd(); ++it )
526 currentDist = pointGeom->
distance( *currentLine );
527 if ( currentDist < minDist )
529 minDist = currentDist;
530 closestLine = currentLine;
549 double currentBufferDist = tolerance;
552 for (
int i = 0; i < maxLoops; ++i )
555 QgsGeometry* clipBaselineBuffer = clippedBaseline->
buffer( currentBufferDist, 8 );
556 if ( !clipBaselineBuffer )
558 delete clipBaselineBuffer;
569 if ( bufferMultiPolygon.size() < 1 )
571 delete clipBaselineBuffer;
575 for (
int j = 0; j < bufferMultiPolygon.size(); ++j )
577 int size = bufferMultiPolygon.at( j ).size();
578 for (
int k = 0; k < size; ++k )
580 mpl.append( bufferMultiPolygon.at( j ).at( k ) );
588 if ( bufferPolygon.size() < 1 )
590 delete clipBaselineBuffer;
594 int size = bufferPolygon.size();
595 for (
int j = 0; j < size; ++j )
597 mpl.append( bufferPolygon[j] );
601 bufferLineClipped = bufferLine->
intersection( stratumGeom );
604 if ( bufferLineClipped && bufferLineClipped->
type() ==
QGis::Line )
607 bool bufferLineClippedIntersectsStratum =
true;
611 QVector<QgsPolygon>::const_iterator multiIt = multiPoly.constBegin();
612 for ( ; multiIt != multiPoly.constEnd(); ++multiIt )
617 bufferLineClippedIntersectsStratum =
false;
625 if ( bufferLineClippedIntersectsStratum )
627 delete clipBaselineBuffer;
628 return bufferLineClipped;
632 delete bufferLineClipped;
633 delete clipBaselineBuffer;
634 currentBufferDist /= 2;
Wrapper for iterator of features from vector data provider or vector layer.
A rectangle specified with double values.
int createSample(QProgressDialog *pd)
double length()
get length of geometry using GEOS
const QgsField & field(int fieldIdx) const
Get field at particular index (must be in range 0..N-1)
QgsMultiPolyline asMultiPolyline() const
return contents of the geometry as a multi linestring if wkbType is WKBMultiLineString, otherwise an empty list
void setSourceCrs(long srsid)
sets source spatial reference system (by QGIS CRS)
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
QVector< QgsPoint > QgsPolyline
polyline is represented as a vector of points
QgsGeometry * geometry() const
Get the geometry object associated with this feature.
QgsPolygon asPolygon() const
return contents of the geometry as a polygon if wkbType is WKBPolygon, otherwise an empty list ...
double closestSegmentWithContext(const QgsPoint &point, QgsPoint &minDistPoint, int &afterVertex, double *leftOf=0, double epsilon=DEFAULT_SEGMENT_EPSILON)
Searches for the closest segment of geometry to the given point.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QGis::GeometryType type() const
Returns type of the vector.
Container of fields for a vector layer.
bool setAttribute(int field, const QVariant &attr)
Set an attribute by id.
WkbType
Used for symbology operations.
A convenience class for writing vector files to disk.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
double sqrDist(double x, double y) const
Returns the squared distance between this point and x,y.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
QList< QgsFeatureId > intersects(QgsRectangle rect) const
returns features that intersect the specified rectangle
QgsMultiPolygon asMultiPolygon() const
return contents of the geometry as a multi polygon if wkbType is WKBMultiPolygon, otherwise an empty ...
void setGeometry(const QgsGeometry &geom)
Set this feature's geometry from another QgsGeometry object (deep copy)
QgsGeometry * buffer(double distance, int segments)
Returns a buffer region around this geometry having the given width and with a specified number of se...
QgsTransectSample(QgsVectorLayer *strataLayer, QString strataIdAttribute, QString minDistanceAttribute, QString nPointsAttribute, DistanceUnits minDistUnits, QgsVectorLayer *baselineLayer, bool shareBaseline, QString baselineStrataId, const QString &outputPointLayer, const QString &outputLineLayer, const QString &usedBaselineLayer, double minTransectLength=0.0)
double measure(QgsGeometry *geometry)
general measurement (line distance or polygon area)
double bearing(const QgsPoint &p1, const QgsPoint &p2)
compute bearing - in radians
double sqrDistToSegment(double x1, double y1, double x2, double y2, QgsPoint &minDistPoint, double epsilon=DEFAULT_SEGMENT_EPSILON) const
Returns the minimum distance between this point and a segment.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QVector< QgsPolygon > QgsMultiPolygon
a collection of QgsPolygons that share a common collection of attributes
void mt_srand(unsigned value)
bool addFeature(QgsFeature &feature, QgsFeatureRendererV2 *renderer=0, QGis::UnitType outputUnit=QGis::Meters)
add feature to the currently opened shapefile
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Append a field. The field must have unique name, otherwise it is rejected (returns false) ...
QGis::WkbType wkbType() const
Returns type of wkb (point / linestring / polygon etc.)
Encapsulate a field in an attribute table or data source.
QVector< QgsPolyline > QgsPolygon
polygon: first item of the list is outer ring, inner rings (if any) start from second item ...
QgsGeometry * intersection(QgsGeometry *geometry)
Returns a geometry representing the points shared by this geometry and other.
A class to represent a point.
static QgsGeometry * fromPoint(const QgsPoint &point)
construct geometry from a point
QVector< QgsPolyline > QgsMultiPolyline
a collection of QgsPolylines that share a common collection of attributes
static QgsGeometry * fromMultiPolyline(const QgsMultiPolyline &multiline)
construct geometry from a multipolyline
General purpose distance and area calculator.
QgsPolyline asPolyline() const
return contents of the geometry as a polyline if wkbType is WKBLineString, otherwise an empty list ...
QgsRectangle boundingBox()
Returns the bounding box of this feature.
virtual long featureCount() const
Number of features in the layer.
bool insertFeature(const QgsFeature &f)
add feature to index
WriterError hasError()
checks whether there were any errors in constructor
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
bool isMultipart() const
Returns true if wkb of the geometry is of WKBMulti* type.
Class for storing a coordinate reference system (CRS)
double measureLine(const QList< QgsPoint > &points)
measures line
static QgsGeometry * fromPolyline(const QgsPolyline &polyline)
construct geometry from a polyline
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
static QgsGeometry * fromPolygon(const QgsPolygon &polygon)
construct geometry from a polygon
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
QgsGeometry * interpolate(double distance)
bool nextFeature(QgsFeature &f)
QgsGeometry * geometryAndOwnership()
Get the geometry object associated with this feature The caller assumes responsibility for the QgsGeo...
QgsPoint asPoint() const
return contents of the geometry as a point if wkbType is WKBPoint, otherwise returns [0...
bool intersects(const QgsRectangle &r) const
Test for intersection with a rectangle (uses GEOS)
Represents a vector layer which manages a vector based data sets.
void setEllipsoidalMode(bool flag)
sets whether coordinates must be projected to ellipsoid before measuring
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
double distance(QgsGeometry &geom)
QGis::UnitType mapUnits() const