mirror of
https://github.com/qgis/QGIS.git
synced 2025-03-23 00:05:43 -04:00
[Geometry checker] Add point must be covered by line check
This commit is contained in:
parent
7fb1c5515b
commit
ee47d42d85
@ -18,6 +18,7 @@ SET (geometrychecker_SRCS
|
||||
checks/qgsgeometrymultipartcheck.cpp
|
||||
checks/qgsgeometrycontainedcheck.cpp
|
||||
checks/qgsgeometryoverlapcheck.cpp
|
||||
checks/qgsgeometrypointcoveredbylinecheck.cpp
|
||||
checks/qgsgeometrysegmentlengthcheck.cpp
|
||||
checks/qgsgeometryselfcontactcheck.cpp
|
||||
checks/qgsgeometryselfintersectioncheck.cpp
|
||||
@ -55,6 +56,7 @@ SET (geometrychecker_MOC_HDRS
|
||||
checks/qgsgeometrymultipartcheck.h
|
||||
checks/qgsgeometrycontainedcheck.h
|
||||
checks/qgsgeometryoverlapcheck.h
|
||||
checks/qgsgeometrypointcoveredbylinecheck.h
|
||||
checks/qgsgeometrysegmentlengthcheck.h
|
||||
checks/qgsgeometryselfcontactcheck.h
|
||||
checks/qgsgeometryselfintersectioncheck.h
|
||||
|
@ -0,0 +1,86 @@
|
||||
/***************************************************************************
|
||||
qgsgeometrypointcoveredbylinecheck.cpp
|
||||
---------------------
|
||||
begin : June 2017
|
||||
copyright : (C) 2017 by Sandro Mani / Sourcepole AG
|
||||
email : smani at sourcepole dot ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsgeometrypointcoveredbylinecheck.h"
|
||||
#include "qgslinestring.h"
|
||||
#include "../utils/qgsfeaturepool.h"
|
||||
|
||||
void QgsGeometryPointCoveredByLineCheck::collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &/*messages*/, QAtomicInt *progressCounter, const QMap<QString, QgsFeatureIds> &ids ) const
|
||||
{
|
||||
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
|
||||
QgsGeometryCheckerUtils::LayerFeatures layerFeatures( mContext->featurePools, featureIds, mCompatibleGeometryTypes, progressCounter, true );
|
||||
for ( const QgsGeometryCheckerUtils::LayerFeature &layerFeature : layerFeatures )
|
||||
{
|
||||
const QgsAbstractGeometry *geom = layerFeature.geometry();
|
||||
for ( int iPart = 0, nParts = geom->partCount(); iPart < nParts; ++iPart )
|
||||
{
|
||||
const QgsPoint *point = dynamic_cast<const QgsPoint *>( QgsGeometryCheckerUtils::getGeomPart( geom, iPart ) );
|
||||
if ( !point )
|
||||
{
|
||||
// Should not happen
|
||||
continue;
|
||||
}
|
||||
// Check that point lies on a line
|
||||
bool touches = false;
|
||||
QgsRectangle rect( point->x() - mContext->tolerance, point->y() - mContext->tolerance,
|
||||
point->x() + mContext->tolerance, point->y() + mContext->tolerance );
|
||||
QgsGeometryCheckerUtils::LayerFeatures checkFeatures( mContext->featurePools, featureIds.keys(), rect, {QgsWkbTypes::LineGeometry} );
|
||||
for ( const QgsGeometryCheckerUtils::LayerFeature &checkFeature : checkFeatures )
|
||||
{
|
||||
const QgsAbstractGeometry *testGeom = checkFeature.geometry();
|
||||
for ( int jPart = 0, mParts = testGeom->partCount(); jPart < mParts; ++jPart )
|
||||
{
|
||||
const QgsLineString *testLine = dynamic_cast<const QgsLineString *>( QgsGeometryCheckerUtils::getGeomPart( testGeom, jPart ) );
|
||||
if ( !testLine )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ( QgsGeometryCheckerUtils::pointOnLine( *point, testLine, mContext->tolerance ) )
|
||||
{
|
||||
touches = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( touches == true )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( touches == true )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
errors.append( new QgsGeometryCheckError( this, layerFeature, *point, QgsVertexId( iPart, 0, 0 ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsGeometryPointCoveredByLineCheck::fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes & /*changes*/ ) const
|
||||
{
|
||||
if ( method == NoChange )
|
||||
{
|
||||
error->setFixed( method );
|
||||
}
|
||||
else
|
||||
{
|
||||
error->setFixFailed( tr( "Unknown method" ) );
|
||||
}
|
||||
}
|
||||
|
||||
QStringList QgsGeometryPointCoveredByLineCheck::getResolutionMethods() const
|
||||
{
|
||||
static QStringList methods = QStringList() << tr( "No action" );
|
||||
return methods;
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/***************************************************************************
|
||||
qgsgeometrypointcoveredbylinecheck.h
|
||||
---------------------
|
||||
begin : June 2017
|
||||
copyright : (C) 2017 by Sandro Mani / Sourcepole AG
|
||||
email : smani at sourcepole dot ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSGEOMETRYPOINTCOVEREDBYLINECHECK_H
|
||||
#define QGSGEOMETRYPOINTCOVEREDBYLINECHECK_H
|
||||
|
||||
#include "qgsgeometrycheck.h"
|
||||
|
||||
class QgsGeometryPointCoveredByLineCheck : public QgsGeometryCheck
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QgsGeometryPointCoveredByLineCheck( QgsGeometryCheckerContext *context )
|
||||
: QgsGeometryCheck( FeatureNodeCheck, {QgsWkbTypes::PointGeometry}, context )
|
||||
{}
|
||||
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const override;
|
||||
void fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> &mergeAttributeIndices, Changes &changes ) const override;
|
||||
QStringList getResolutionMethods() const override;
|
||||
QString errorDescription() const override { return tr( "Point not covered by line" ); }
|
||||
QString errorName() const override { return QStringLiteral( "QgsGeometryPointCoveredByLineCheck" ); }
|
||||
private:
|
||||
enum ResolutionMethod { NoChange };
|
||||
};
|
||||
|
||||
#endif // QGSGEOMETRYPOINTCOVEREDBYLINECHECK_H
|
@ -27,6 +27,7 @@
|
||||
#include "checks/qgsgeometryholecheck.h"
|
||||
#include "checks/qgsgeometrymultipartcheck.h"
|
||||
#include "checks/qgsgeometryoverlapcheck.h"
|
||||
#include "checks/qgsgeometrypointcoveredbylinecheck.h"
|
||||
#include "checks/qgsgeometrysegmentlengthcheck.h"
|
||||
#include "checks/qgsgeometryselfcontactcheck.h"
|
||||
#include "checks/qgsgeometryselfintersectioncheck.h"
|
||||
@ -356,6 +357,34 @@ REGISTER_QGS_GEOMETRY_CHECK_FACTORY( QgsGeometryCheckFactoryT<QgsGeometryOverlap
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<> void QgsGeometryCheckFactoryT<QgsGeometryPointCoveredByLineCheck>::restorePrevious( Ui::QgsGeometryCheckerSetupTab &ui ) const
|
||||
{
|
||||
ui.checkPointCoveredByLine->setChecked( QgsSettings().value( sSettingsGroup + "checkPointCoveredByLine" ).toBool() );
|
||||
}
|
||||
|
||||
template<> bool QgsGeometryCheckFactoryT<QgsGeometryPointCoveredByLineCheck>::checkApplicability( Ui::QgsGeometryCheckerSetupTab &ui, int nPoint, int /*nLineString*/, int /*nPolygon*/ ) const
|
||||
{
|
||||
ui.checkPointCoveredByLine->setEnabled( nPoint > 0 );
|
||||
return ui.checkPointCoveredByLine->isEnabled();
|
||||
}
|
||||
|
||||
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryPointCoveredByLineCheck>::createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const
|
||||
{
|
||||
QgsSettings().setValue( sSettingsGroup + "checkPointCoveredByLine", ui.checkPointCoveredByLine->isChecked() );
|
||||
if ( ui.checkPointCoveredByLine->isEnabled() && ui.checkPointCoveredByLine->isChecked() )
|
||||
{
|
||||
return new QgsGeometryPointCoveredByLineCheck( context );
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_QGS_GEOMETRY_CHECK_FACTORY( QgsGeometryCheckFactoryT<QgsGeometryPointCoveredByLineCheck> )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<> void QgsGeometryCheckFactoryT<QgsGeometrySegmentLengthCheck>::restorePrevious( Ui::QgsGeometryCheckerSetupTab &ui ) const
|
||||
{
|
||||
ui.checkBoxSegmentLength->setChecked( QgsSettings().value( sSettingsGroup + "checkSegmentLength" ).toBool() );
|
||||
|
@ -43,7 +43,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>626</width>
|
||||
<height>872</height>
|
||||
<height>895</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
@ -485,30 +485,16 @@
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxDuplicates">
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxGaps">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Check for duplicates</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBoxOverlapArea">
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBoxGapArea">
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>999999999.000000000000000</double>
|
||||
<string>Check for gaps smaller than (map units sqr.)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -525,16 +511,10 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxGaps">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxDuplicates">
|
||||
<property name="text">
|
||||
<string>Check for gaps smaller than (map units sqr.)</string>
|
||||
<string>Check for duplicates</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -545,13 +525,40 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<item row="3" column="1">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBoxGapArea">
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string><i>Note: Topology checks are performed in the current map CRS.</i></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBoxOverlapArea">
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkPointCoveredByLine">
|
||||
<property name="text">
|
||||
<string>Points must be covered by lines</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -213,7 +213,7 @@ namespace QgsGeometryCheckerUtils
|
||||
{
|
||||
QgsPoint p1 = line->vertexAt( QgsVertexId( 0, 0, i ) );
|
||||
QgsPoint p2 = line->vertexAt( QgsVertexId( 0, 0, i + 1 ) );
|
||||
double dist = pointLineDist( p1, p2, 1 );
|
||||
double dist = pointLineDist( p1, p2, p );
|
||||
if ( dist < tol )
|
||||
{
|
||||
return true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user