mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
- GEOSInterpolate only available in GEOS>=3.2
- sync QgsGeometry sip bindings with C++
This commit is contained in:
parent
a4670f04d3
commit
2d9115fa56
@ -1,10 +1,10 @@
|
||||
|
||||
/** polyline is just a list of points */
|
||||
/** polyline is represented as a vector of points */
|
||||
typedef QVector<QgsPoint> QgsPolyline;
|
||||
|
||||
/** polygon: first item of the list is outer ring, inner rings (if any) start from second item */
|
||||
typedef QVector< QVector<QgsPoint> > QgsPolygon;
|
||||
|
||||
|
||||
/** a collection of QgsPoints that share a common collection of attributes */
|
||||
typedef QVector<QgsPoint> QgsMultiPoint;
|
||||
|
||||
@ -23,36 +23,34 @@ class QgsGeometry
|
||||
%End
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
QgsGeometry();
|
||||
|
||||
|
||||
/** copy constructor will prompt a deep copy of the object */
|
||||
QgsGeometry( const QgsGeometry & );
|
||||
|
||||
|
||||
|
||||
//! Destructor
|
||||
~QgsGeometry();
|
||||
|
||||
|
||||
/** static method that creates geometry from Wkt */
|
||||
static QgsGeometry* fromWkt(QString wkt) /Factory/;
|
||||
|
||||
static QgsGeometry* fromWkt( QString wkt ) /Factory/;
|
||||
|
||||
/** construct geometry from a point */
|
||||
static QgsGeometry* fromPoint(const QgsPoint& point) /Factory/;
|
||||
static QgsGeometry* fromPoint( const QgsPoint& point ) /Factory/;
|
||||
/** construct geometry from a multipoint */
|
||||
static QgsGeometry* fromMultiPoint(const QgsMultiPoint& multipoint) /Factory/;
|
||||
static QgsGeometry* fromMultiPoint( const QgsMultiPoint& multipoint ) /Factory/;
|
||||
/** construct geometry from a polyline */
|
||||
static QgsGeometry* fromPolyline(const QgsPolyline& polyline) /Factory/;
|
||||
static QgsGeometry* fromPolyline( const QgsPolyline& polyline ) /Factory/;
|
||||
/** construct geometry from a multipolyline*/
|
||||
static QgsGeometry* fromMultiPolyline(const QgsMultiPolyline& multiline) /Factory/;
|
||||
static QgsGeometry* fromMultiPolyline( const QgsMultiPolyline& multiline ) /Factory/;
|
||||
/** construct geometry from a polygon */
|
||||
static QgsGeometry* fromPolygon(const QgsPolygon& polygon) /Factory/;
|
||||
static QgsGeometry* fromPolygon( const QgsPolygon& polygon ) /Factory/;
|
||||
/** construct geometry from a multipolygon */
|
||||
static QgsGeometry* fromMultiPolygon(const QgsMultiPolygon& multipoly) /Factory/;
|
||||
static QgsGeometry* fromMultiPolygon( const QgsMultiPolygon& multipoly ) /Factory/;
|
||||
/** construct geometry from a rectangle */
|
||||
static QgsGeometry* fromRect(const QgsRectangle& rect) /Factory/;
|
||||
|
||||
static QgsGeometry* fromRect( const QgsRectangle& rect ) /Factory/;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@ -77,10 +75,10 @@ class QgsGeometry
|
||||
%End
|
||||
|
||||
/**
|
||||
Returns the size of the WKB in asWkb().
|
||||
*/
|
||||
* Returns the size of the WKB in asWkb().
|
||||
*/
|
||||
size_t wkbSize();
|
||||
|
||||
|
||||
/** Returns type of wkb (point / linestring / polygon etc.) */
|
||||
QGis::WkbType wkbType();
|
||||
|
||||
@ -105,29 +103,24 @@ class QgsGeometry
|
||||
*/
|
||||
bool isGeosEmpty();
|
||||
|
||||
/**
|
||||
Set the geometry, feeding in a geometry in GEOS format.
|
||||
*/
|
||||
// TODO: unsupported class... would be possible to use PyGEOS?
|
||||
//void fromGeos(geos::Geometry* geos);
|
||||
|
||||
/** get area using GEOS
|
||||
/** get area of geometry using GEOS
|
||||
@note added in 1.5
|
||||
*/
|
||||
double area();
|
||||
|
||||
/** get length using GEOS
|
||||
/** get length of geometry using GEOS
|
||||
@note added in 1.5
|
||||
*/
|
||||
double length();
|
||||
|
||||
double distance(QgsGeometry& geom);
|
||||
double distance( QgsGeometry& geom );
|
||||
|
||||
/**
|
||||
Returns the vertex closest to the given point
|
||||
(and also vertex index, squared distance and indexes of the vertices before/after)
|
||||
Returns the vertex closest to the given point, the corresponding vertex index, squared distance snap point / target point
|
||||
and the indices of the vertices before/after. The vertices before/after are -1 if not present
|
||||
*/
|
||||
QgsPoint closestVertex(const QgsPoint& point, int& atVertex /Out/, int& beforeVertex /Out/, int& afterVertex /Out/, double& sqrDist /Out/);
|
||||
QgsPoint closestVertex( const QgsPoint& point, int& atVertex /Out/, int& beforeVertex /Out/, int& afterVertex /Out/, double& sqrDist /Out/);
|
||||
|
||||
|
||||
/**
|
||||
Returns the indexes of the vertices before and after the given vertex index.
|
||||
@ -141,32 +134,33 @@ class QgsGeometry
|
||||
account the first vertex is equal to the last vertex (and will
|
||||
skip equal vertex positions).
|
||||
*/
|
||||
void adjacentVertices(int atVertex, int& beforeVertex /Out/, int& afterVertex /Out/);
|
||||
void adjacentVertices( int atVertex, int& beforeVertex /Out/, int& afterVertex /Out/ );
|
||||
|
||||
|
||||
/** Insert a new vertex before the given vertex index,
|
||||
* ring and item (first number is index 0)
|
||||
* If the requested vertex number (beforeVertex.back()) is greater
|
||||
* than the last actual vertex on the requested ring and item,
|
||||
* it is assumed that the vertex is to be appended instead of inserted.
|
||||
* Returns FALSE if atVertex does not correspond to a valid vertex
|
||||
* Returns false if atVertex does not correspond to a valid vertex
|
||||
* on this geometry (including if this geometry is a Point).
|
||||
* It is up to the caller to distinguish between
|
||||
* these error conditions. (Or maybe we add another method to this
|
||||
* object to help make the distinction?)
|
||||
*/
|
||||
bool insertVertex(double x, double y, int beforeVertex);
|
||||
bool insertVertex( double x, double y, int beforeVertex );
|
||||
|
||||
/** Moves the vertex at the given position number,
|
||||
* ring and item (first number is index 0)
|
||||
/** Moves the vertex at the given position number
|
||||
* and item (first number is index 0)
|
||||
* to the given coordinates.
|
||||
* Returns FALSE if atVertex does not correspond to a valid vertex
|
||||
* on this geometry
|
||||
* Returns false if atVertex does not correspond to a valid vertex
|
||||
* on this geometry
|
||||
*/
|
||||
bool moveVertex(double x, double y, int atVertex);
|
||||
|
||||
/** Deletes the vertex at the given position number,
|
||||
* ring and item (first number is index 0)
|
||||
* Returns FALSE if atVertex does not correspond to a valid vertex
|
||||
bool moveVertex( double x, double y, int atVertex );
|
||||
|
||||
/** Deletes the vertex at the given position number and item
|
||||
* (first number is index 0)
|
||||
* Returns false if atVertex does not correspond to a valid vertex
|
||||
* on this geometry (including if this geometry is a Point),
|
||||
* or if the number of remaining verticies in the linestring
|
||||
* would be less than two.
|
||||
@ -174,87 +168,95 @@ class QgsGeometry
|
||||
* these error conditions. (Or maybe we add another method to this
|
||||
* object to help make the distinction?)
|
||||
*/
|
||||
bool deleteVertex(int atVertex);
|
||||
bool deleteVertex( int atVertex );
|
||||
|
||||
/**
|
||||
* Returns coordinates of a vertex.
|
||||
* @param atVertex index of the vertex
|
||||
* @return Coordinates of the vertex or QgsPoint(0,0) on error
|
||||
*/
|
||||
QgsPoint vertexAt(int atVertex);
|
||||
QgsPoint vertexAt( int atVertex );
|
||||
|
||||
/**
|
||||
Returns the squared cartesian distance between the given point
|
||||
to the given vertex index*/
|
||||
double sqrDistToVertexAt(QgsPoint& point /In/, int atVertex);
|
||||
* Returns the squared cartesian distance between the given point
|
||||
* to the given vertex index (vertex at the given position number,
|
||||
* ring and item (first number is index 0))
|
||||
*/
|
||||
double sqrDistToVertexAt( QgsPoint& point /In/, int atVertex );
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Searches for the the closest vertex in this geometry to the given point.
|
||||
* @param point Specifiest the point for search
|
||||
* @param atVertex Receives index of the closest vertex
|
||||
* @return The squared cartesian distance is also returned in sqrDist, negative number on error
|
||||
*/
|
||||
double closestVertexWithContext(const QgsPoint& point, int& atVertex /Out/);
|
||||
double closestVertexWithContext( const QgsPoint& point, int& atVertex /Out/ );
|
||||
|
||||
/**
|
||||
* Searches for the closest segment of geometry to the given point
|
||||
* @param point Specifies the point for search
|
||||
* @param minDistPoint Receives the nearest point on the segment
|
||||
* @param beforeVertex Receives index of the vertex before the closest segment
|
||||
* @param afterVertex Receives index of the vertex after the closest segment. The vertex
|
||||
* before the closest segment is always afterVertex - 1
|
||||
* @param leftOf Out: Returns if the point lies on the left of right side of the segment ( < 0 means left, > 0 means right )
|
||||
* @param epsilon epsilon for segment snapping (added in 1.8)
|
||||
* @return The squared cartesian distance is also returned in sqrDist, negative number on error
|
||||
*/
|
||||
double closestSegmentWithContext(const QgsPoint& point, QgsPoint& minDistPoint /Out/, int& beforeVertex /Out/);
|
||||
double closestSegmentWithContext( const QgsPoint& point, QgsPoint& minDistPoint /Out/, int& beforeVertex /Out/ );
|
||||
|
||||
/**Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
|
||||
@return 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed, \
|
||||
/**Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
|
||||
@return 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed,
|
||||
3 ring is not valid geometry, 4 ring not disjoint with existing rings, 5 no polygon found which contained the ring*/
|
||||
int addRing(const QList<QgsPoint>& ring);
|
||||
int addRing( const QList<QgsPoint>& ring );
|
||||
|
||||
/**Adds a new island polygon to a multipolygon feature
|
||||
@return 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring \
|
||||
not disjoint with existing polygons of the feature*/
|
||||
int addPart(const QList<QgsPoint>& ring);
|
||||
/**Adds a new island polygon to a multipolygon feature
|
||||
@return 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring
|
||||
not disjoint with existing polygons of the feature*/
|
||||
int addPart( const QList<QgsPoint>& ring );
|
||||
int addIsland( const QList<QgsPoint> &ring ) /Deprecated/;
|
||||
|
||||
/**Translate this geometry by dx, dy
|
||||
/**Translate this geometry by dx, dy
|
||||
@return 0 in case of success*/
|
||||
int translate(double dx, double dy);
|
||||
int translate( double dx, double dy );
|
||||
|
||||
/**Transform this geometry as described by CoordinateTranasform ct
|
||||
/**Transform this geometry as described by CoordinateTranasform ct
|
||||
@return 0 in case of success*/
|
||||
int transform( const QgsCoordinateTransform& ct );
|
||||
|
||||
/**Splits this geometry according to a given line. Note that the geometry is only split once. If there are several intersections
|
||||
between geometry and splitLine, only the first one is considered.
|
||||
/**Splits this geometry according to a given line. Note that the geometry is only split once. If there are several intersections
|
||||
between geometry and splitLine, only the first one is considered.
|
||||
@param splitLine the line that splits the geometry
|
||||
@param newGeometrys OUT: list of new geometries that have been created with the split
|
||||
@param[out] newGeometries list of new geometries that have been created with the split
|
||||
@param topological true if topological editing is enabled
|
||||
@topologyTestPoints OUT: points that need to be tested for topological completeness in the dataset
|
||||
@param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
|
||||
@return 0 in case of success, 1 if geometry has not been split, error else*/
|
||||
int splitGeometry(const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries /Out/, bool topological, QList<QgsPoint>& topologyTestPoints /Out/);
|
||||
int splitGeometry( const QList<QgsPoint>& splitLine,
|
||||
QList<QgsGeometry*>&newGeometries /Out/,
|
||||
bool topological,
|
||||
QList<QgsPoint> &topologyTestPoints /Out/);
|
||||
|
||||
/**Replaces a part of this geometry with another line
|
||||
/**Replaces a part of this geometry with another line
|
||||
@return 0 in case of success
|
||||
@note: this function was added in version 1.3*/
|
||||
int reshapeGeometry( const QList<QgsPoint>& reshapeWithLine );
|
||||
|
||||
/**Changes this geometry such that it does not intersect the other geometry
|
||||
/**Changes this geometry such that it does not intersect the other geometry
|
||||
@param other geometry that should not be intersect
|
||||
@return 0 in case of success*/
|
||||
int makeDifference(QgsGeometry* other);
|
||||
int makeDifference( QgsGeometry* other );
|
||||
|
||||
/**Returns the bounding box of this feature*/
|
||||
QgsRectangle boundingBox();
|
||||
|
||||
/** Test for intersection with a rectangle (uses GEOS) */
|
||||
bool intersects(const QgsRectangle& r);
|
||||
/** Test for intersection with a geoemetry (uses GEOS) */
|
||||
bool intersects(QgsGeometry* geometry);
|
||||
bool intersects( const QgsRectangle& r );
|
||||
|
||||
/** Test for intersection with a geometry (uses GEOS) */
|
||||
bool intersects( QgsGeometry* geometry );
|
||||
|
||||
/** Test for containment of a point (uses GEOS) */
|
||||
bool contains(QgsPoint* p);
|
||||
|
||||
bool contains( QgsPoint* p );
|
||||
|
||||
/** Test for if geometry is contained in an other (uses GEOS)
|
||||
* @note added in 1.5 */
|
||||
bool contains( QgsGeometry* geometry );
|
||||
@ -285,11 +287,11 @@ not disjoint with existing polygons of the feature*/
|
||||
|
||||
/** Returns a buffer region around this geometry having the given width and with a specified number
|
||||
of segments used to approximate curves */
|
||||
QgsGeometry* buffer(double distance, int segments) /Factory/;
|
||||
QgsGeometry* buffer( double distance, int segments ) /Factory/;
|
||||
|
||||
/** Returns a simplified version of this geometry using a specified tolerance value */
|
||||
QgsGeometry* simplify(double tolerance) /Factory/;
|
||||
|
||||
QgsGeometry* simplify( double tolerance ) /Factory/;
|
||||
|
||||
/** Returns the center of mass of a geometry
|
||||
* @note for line based geometries, the center point of the line is returned,
|
||||
* and for point based geometries, the point itself is returned */
|
||||
@ -298,53 +300,59 @@ not disjoint with existing polygons of the feature*/
|
||||
/** Returns the smallest convex polygon that contains all the points in the geometry. */
|
||||
QgsGeometry* convexHull() /Factory/;
|
||||
|
||||
/* Return interpolated point on line at distance
|
||||
* @note added in 1.9
|
||||
*/
|
||||
QgsGeometry* interpolate( double distance ) /Factory/;
|
||||
|
||||
|
||||
/** Returns a geometry representing the points shared by this geometry and other. */
|
||||
QgsGeometry* intersection(QgsGeometry* geometry) /Factory/;
|
||||
|
||||
QgsGeometry* intersection( QgsGeometry* geometry ) /Factory/;
|
||||
|
||||
/** Returns a geometry representing all the points in this geometry and other (a
|
||||
* union geometry operation).
|
||||
* union geometry operation).
|
||||
* @note this operation is not called union since its a reserved word in C++.*/
|
||||
QgsGeometry* combine( QgsGeometry* geometry ) /Factory/;
|
||||
|
||||
|
||||
/** Returns a geometry representing the points making up this geometry that do not make up other. */
|
||||
QgsGeometry* difference(QgsGeometry* geometry) /Factory/;
|
||||
|
||||
QgsGeometry* difference( QgsGeometry* geometry ) /Factory/;
|
||||
|
||||
/** Returns a Geometry representing the points making up this Geometry that do not make up other. */
|
||||
QgsGeometry* symDifference(QgsGeometry* geometry) /Factory/;
|
||||
|
||||
/**Creates a geos geometry from this features geometry. Note, that the returned object needs to be deleted*/
|
||||
// TODO: unsupported class... would be possible to use PyGEOS?
|
||||
//geos::Geometry* geosGeometry() const;
|
||||
QgsGeometry* symDifference( QgsGeometry* geometry ) /Factory/;
|
||||
|
||||
/** Exports the geometry to mWkt
|
||||
@return true in case of success and false else
|
||||
* @return true in case of success and false else
|
||||
*/
|
||||
QString exportToWkt();
|
||||
|
||||
|
||||
/** Exports the geometry to mGeoJSON
|
||||
* @return true in case of success and false else
|
||||
* @note added in 1.8
|
||||
* @note python binding added in 1.9
|
||||
*/
|
||||
QString exportToGeoJSON();
|
||||
|
||||
/* Accessor functions for getting geometry data */
|
||||
|
||||
|
||||
/** return contents of the geometry as a point
|
||||
if wkbType is WKBPoint, otherwise returns [0,0] */
|
||||
QgsPoint asPoint();
|
||||
|
||||
|
||||
/** return contents of the geometry as a polyline
|
||||
if wkbType is WKBLineString, otherwise an empty list */
|
||||
QgsPolyline asPolyline();
|
||||
|
||||
|
||||
/** return contents of the geometry as a polygon
|
||||
if wkbType is WKBPolygon, otherwise an empty list */
|
||||
QgsPolygon asPolygon();
|
||||
|
||||
|
||||
/** return contents of the geometry as a multi point
|
||||
if wkbType is WKBMultiPint, otherwise an empty list */
|
||||
if wkbType is WKBMultiPoint, otherwise an empty list */
|
||||
QgsMultiPoint asMultiPoint();
|
||||
|
||||
|
||||
/** return contents of the geometry as a multi linestring
|
||||
if wkbType is WKBMultiLineString, otherwise an empty list */
|
||||
QgsMultiPolyline asMultiPolyline();
|
||||
|
||||
|
||||
/** return contents of the geometry as a multi polygon
|
||||
if wkbType is WKBMultiPolygon, otherwise an empty list */
|
||||
QgsMultiPolygon asMultiPolygon();
|
||||
@ -356,12 +364,12 @@ not disjoint with existing polygons of the feature*/
|
||||
|
||||
/** delete a ring in polygon or multipolygon.
|
||||
Ring 0 is outer ring and can't be deleted.
|
||||
@return TRUE on success
|
||||
@return true on success
|
||||
@note added in version 1.2 */
|
||||
bool deleteRing( int ringNum, int partNum = 0 );
|
||||
|
||||
/** delete part identified by the part number
|
||||
@return TRUE on success
|
||||
@return true on success
|
||||
@note added in version 1.2 */
|
||||
bool deletePart( int partNum );
|
||||
|
||||
@ -388,7 +396,7 @@ not disjoint with existing polygons of the feature*/
|
||||
QgsPoint where();
|
||||
bool hasWhere();
|
||||
};
|
||||
|
||||
|
||||
/** Validate geometry and produce a list of geometry errors
|
||||
* @note python binding added in 1.6
|
||||
**/
|
||||
|
@ -6411,20 +6411,25 @@ QgsGeometry* QgsGeometry::convexHull()
|
||||
|
||||
QgsGeometry* QgsGeometry::interpolate( double distance )
|
||||
{
|
||||
if ( !mGeos )
|
||||
{
|
||||
exportWkbToGeos();
|
||||
}
|
||||
if ( !mGeos )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
|
||||
((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=2)))
|
||||
if ( !mGeos )
|
||||
{
|
||||
exportWkbToGeos();
|
||||
}
|
||||
if ( !mGeos )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return fromGeosGeom( GEOSInterpolate( mGeos, distance ) );
|
||||
}
|
||||
CATCH_GEOS( 0 )
|
||||
try
|
||||
{
|
||||
return fromGeosGeom( GEOSInterpolate( mGeos, distance ) );
|
||||
}
|
||||
CATCH_GEOS( 0 )
|
||||
#else
|
||||
QgsMessageLog::logMessage( QObject::tr( "GEOS prior to 3.2 doesn't support GEOSInterpolate" ), QObject::tr( "GEOS" ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
QgsGeometry* QgsGeometry::intersection( QgsGeometry* geometry )
|
||||
|
@ -113,8 +113,8 @@ class CORE_EXPORT QgsGeometry
|
||||
unsigned char * asWkb();
|
||||
|
||||
/**
|
||||
Returns the size of the WKB in asWkb().
|
||||
*/
|
||||
* Returns the size of the WKB in asWkb().
|
||||
*/
|
||||
size_t wkbSize();
|
||||
|
||||
/**Returns a geos geomtry. QgsGeometry keeps ownership, don't delete the returned object!
|
||||
@ -220,10 +220,9 @@ class CORE_EXPORT QgsGeometry
|
||||
QgsPoint vertexAt( int atVertex );
|
||||
|
||||
/**
|
||||
Returns the squared cartesian distance between the given point
|
||||
to the given vertex index (vertex at the given position number,
|
||||
ring and item (first number is index 0))
|
||||
|
||||
* Returns the squared cartesian distance between the given point
|
||||
* to the given vertex index (vertex at the given position number,
|
||||
* ring and item (first number is index 0))
|
||||
*/
|
||||
double sqrDistToVertexAt( QgsPoint& point, int atVertex );
|
||||
|
||||
@ -343,6 +342,9 @@ class CORE_EXPORT QgsGeometry
|
||||
/** Returns the smallest convex polygon that contains all the points in the geometry. */
|
||||
QgsGeometry* convexHull();
|
||||
|
||||
/* Return interpolated point on line at distance
|
||||
* @note added in 1.9
|
||||
*/
|
||||
QgsGeometry* interpolate( double distance );
|
||||
|
||||
/** Returns a geometry representing the points shared by this geometry and other. */
|
||||
@ -360,12 +362,14 @@ class CORE_EXPORT QgsGeometry
|
||||
QgsGeometry* symDifference( QgsGeometry* geometry );
|
||||
|
||||
/** Exports the geometry to mWkt
|
||||
@return true in case of success and false else
|
||||
* @return true in case of success and false else
|
||||
*/
|
||||
QString exportToWkt();
|
||||
|
||||
/** Exports the geometry to mGeoJSON
|
||||
@return true in case of success and false else
|
||||
* @return true in case of success and false else
|
||||
* @note added in 1.8
|
||||
* @note python binding added in 1.9
|
||||
*/
|
||||
QString exportToGeoJSON();
|
||||
|
||||
@ -441,6 +445,7 @@ class CORE_EXPORT QgsGeometry
|
||||
|
||||
/** Validate geometry and produce a list of geometry errors
|
||||
* @note added in 1.5
|
||||
* @note python binding added in 1.6
|
||||
**/
|
||||
void validateGeometry( QList<Error> &errors );
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user