Skip to content

Commit

Permalink
fix python constructor for QgsPoint (does not accept QgsPointXY & QPo…
Browse files Browse the repository at this point in the history
…intF anymore)

fixes #32443

(cherry picked from commit 03baeea)
  • Loading branch information
jef-n committed Oct 28, 2019
1 parent edff9ce commit a022ddc
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 85 deletions.
84 changes: 39 additions & 45 deletions python/core/auto_generated/geometry/qgspoint.sip.in
Expand Up @@ -26,7 +26,7 @@ Point geometry type, with support for z-dimension and m-values.

public:

QgsPoint( SIP_PYOBJECT x = Py_None, SIP_PYOBJECT y = Py_None, SIP_PYOBJECT z = Py_None, SIP_PYOBJECT m = Py_None, QgsWkbTypes::Type wkbType = QgsWkbTypes::Unknown ) [( double x = 0.0, double y = 0.0, double z = 0.0, double m = 0.0, QgsWkbTypes::Type wkbType = QgsWkbTypes::Unknown )];
QgsPoint( SIP_PYOBJECT x = Py_None, SIP_PYOBJECT y = Py_None, SIP_PYOBJECT z = Py_None, SIP_PYOBJECT m = Py_None, SIP_PYOBJECT wkbType = Py_None ) [( double x = 0.0, double y = 0.0, double z = 0.0, double m = 0.0, QgsWkbTypes::Type wkbType = QgsWkbTypes::Unknown )];
%Docstring
Construct a point with the provided initial coordinate values.

Expand All @@ -53,59 +53,53 @@ based on the following rules:
pt.wkbType() # QgsWkbTypes.PointZ
%End
%MethodCode
double x;
double y;
double z;
double m;

if ( a0 == Py_None )
{
x = std::numeric_limits<double>::quiet_NaN();
}
else
{
x = PyFloat_AsDouble( a0 );
}

if ( a1 == Py_None )
if ( sipCanConvertToType( a0, sipType_QgsPointXY, SIP_NOT_NONE ) && a1 == Py_None && a2 == Py_None && a3 == Py_None && a4 == Py_None )
{
y = std::numeric_limits<double>::quiet_NaN();
int state;
int sipIsErr = 0;

QgsPointXY *p = reinterpret_cast<QgsPointXY *>( sipConvertToType( a0, sipType_QgsPointXY, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
if ( sipIsErr )
{
sipReleaseType( p, sipType_QgsPointXY, state );
}
else
{
sipCpp = new sipQgsPoint( QgsPoint( *p ) );
}
}
else
else if ( sipCanConvertToType( a0, sipType_QPointF, SIP_NOT_NONE ) && a1 == Py_None && a2 == Py_None && a3 == Py_None && a4 == Py_None )
{
y = PyFloat_AsDouble( a1 );
int state;
int sipIsErr = 0;

QPointF *p = reinterpret_cast<QPointF *>( sipConvertToType( a0, sipType_QPointF, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
if ( sipIsErr )
{
sipReleaseType( p, sipType_QPointF, state );
}
else
{
sipCpp = new sipQgsPoint( QgsPoint( *p ) );
}
}

if ( a2 == Py_None )
else if (
( a0 == Py_None || PyFloat_AsDouble( a0 ) != -1.0 || !PyErr_Occurred() ) &&
( a1 == Py_None || PyFloat_AsDouble( a1 ) != -1.0 || !PyErr_Occurred() ) &&
( a2 == Py_None || PyFloat_AsDouble( a2 ) != -1.0 || !PyErr_Occurred() ) &&
( a3 == Py_None || PyFloat_AsDouble( a3 ) != -1.0 || !PyErr_Occurred() ) &&
( a4 == Py_None || sipCanConvertToEnum( a4, sipType_QgsWkbTypes_Type ) ) )
{
z = std::numeric_limits<double>::quiet_NaN();
double x = a0 == Py_None ? std::numeric_limits<double>::quiet_NaN() : PyFloat_AsDouble( a0 );
double y = a1 == Py_None ? std::numeric_limits<double>::quiet_NaN() : PyFloat_AsDouble( a1 );
double z = a2 == Py_None ? std::numeric_limits<double>::quiet_NaN() : PyFloat_AsDouble( a2 );
double m = a3 == Py_None ? std::numeric_limits<double>::quiet_NaN() : PyFloat_AsDouble( a3 );
QgsWkbTypes::Type wkbType = a4 == Py_None ? QgsWkbTypes::Unknown : static_cast<QgsWkbTypes::Type>( sipConvertToEnum( a4, sipType_QgsWkbTypes_Type ) );
sipCpp = new sipQgsPoint( QgsPoint( x, y, z, m, wkbType ) );
}
else
{
z = PyFloat_AsDouble( a2 );
}

if ( a3 == Py_None )
{
m = std::numeric_limits<double>::quiet_NaN();
}
else
{
m = PyFloat_AsDouble( a3 );
}

sipCpp = new sipQgsPoint( x, y, z, m, a4 );
%End

explicit QgsPoint( const QgsPointXY &p );
%Docstring
Construct a QgsPoint from a QgsPointXY object
%End

explicit QgsPoint( QPointF p );
%Docstring
Construct a QgsPoint from a QPointF
%End


virtual bool operator==( const QgsAbstractGeometry &other ) const;
Expand Down
78 changes: 40 additions & 38 deletions src/core/geometry/qgspoint.h
Expand Up @@ -32,7 +32,7 @@
/**
* \ingroup core
* \brief Point geometry type, with support for z-dimension and m-values.
* \since QGIS 3.0, (previously QgsPointv2 since QGIS 2.10)
* \since QGIS 3.0, (previously QgsPointV2 since QGIS 2.10)
*/
class CORE_EXPORT QgsPoint: public QgsAbstractGeometry
{
Expand Down Expand Up @@ -73,62 +73,64 @@ class CORE_EXPORT QgsPoint: public QgsAbstractGeometry
#ifndef SIP_RUN
QgsPoint( double x = std::numeric_limits<double>::quiet_NaN(), double y = std::numeric_limits<double>::quiet_NaN(), double z = std::numeric_limits<double>::quiet_NaN(), double m = std::numeric_limits<double>::quiet_NaN(), QgsWkbTypes::Type wkbType = QgsWkbTypes::Unknown );
#else
QgsPoint( SIP_PYOBJECT x = Py_None, SIP_PYOBJECT y = Py_None, SIP_PYOBJECT z = Py_None, SIP_PYOBJECT m = Py_None, QgsWkbTypes::Type wkbType = QgsWkbTypes::Unknown ) [( double x = 0.0, double y = 0.0, double z = 0.0, double m = 0.0, QgsWkbTypes::Type wkbType = QgsWkbTypes::Unknown )];
QgsPoint( SIP_PYOBJECT x = Py_None, SIP_PYOBJECT y = Py_None, SIP_PYOBJECT z = Py_None, SIP_PYOBJECT m = Py_None, SIP_PYOBJECT wkbType = Py_None ) [( double x = 0.0, double y = 0.0, double z = 0.0, double m = 0.0, QgsWkbTypes::Type wkbType = QgsWkbTypes::Unknown )];
% MethodCode
double x;
double y;
double z;
double m;

if ( a0 == Py_None )
{
x = std::numeric_limits<double>::quiet_NaN();
}
else
if ( sipCanConvertToType( a0, sipType_QgsPointXY, SIP_NOT_NONE ) && a1 == Py_None && a2 == Py_None && a3 == Py_None && a4 == Py_None )
{
x = PyFloat_AsDouble( a0 );
}
int state;
int sipIsErr = 0;

if ( a1 == Py_None )
{
y = std::numeric_limits<double>::quiet_NaN();
}
else
{
y = PyFloat_AsDouble( a1 );
}

if ( a2 == Py_None )
{
z = std::numeric_limits<double>::quiet_NaN();
QgsPointXY *p = reinterpret_cast<QgsPointXY *>( sipConvertToType( a0, sipType_QgsPointXY, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
if ( sipIsErr )
{
sipReleaseType( p, sipType_QgsPointXY, state );
}
else
{
sipCpp = new sipQgsPoint( QgsPoint( *p ) );
}
}
else
else if ( sipCanConvertToType( a0, sipType_QPointF, SIP_NOT_NONE ) && a1 == Py_None && a2 == Py_None && a3 == Py_None && a4 == Py_None )
{
z = PyFloat_AsDouble( a2 );
}
int state;
int sipIsErr = 0;

if ( a3 == Py_None )
{
m = std::numeric_limits<double>::quiet_NaN();
QPointF *p = reinterpret_cast<QPointF *>( sipConvertToType( a0, sipType_QPointF, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
if ( sipIsErr )
{
sipReleaseType( p, sipType_QPointF, state );
}
else
{
sipCpp = new sipQgsPoint( QgsPoint( *p ) );
}
}
else
else if (
( a0 == Py_None || PyFloat_AsDouble( a0 ) != -1.0 || !PyErr_Occurred() ) &&
( a1 == Py_None || PyFloat_AsDouble( a1 ) != -1.0 || !PyErr_Occurred() ) &&
( a2 == Py_None || PyFloat_AsDouble( a2 ) != -1.0 || !PyErr_Occurred() ) &&
( a3 == Py_None || PyFloat_AsDouble( a3 ) != -1.0 || !PyErr_Occurred() ) &&
( a4 == Py_None || sipCanConvertToEnum( a4, sipType_QgsWkbTypes_Type ) ) )
{
m = PyFloat_AsDouble( a3 );
double x = a0 == Py_None ? std::numeric_limits<double>::quiet_NaN() : PyFloat_AsDouble( a0 );
double y = a1 == Py_None ? std::numeric_limits<double>::quiet_NaN() : PyFloat_AsDouble( a1 );
double z = a2 == Py_None ? std::numeric_limits<double>::quiet_NaN() : PyFloat_AsDouble( a2 );
double m = a3 == Py_None ? std::numeric_limits<double>::quiet_NaN() : PyFloat_AsDouble( a3 );
QgsWkbTypes::Type wkbType = a4 == Py_None ? QgsWkbTypes::Unknown : static_cast<QgsWkbTypes::Type>( sipConvertToEnum( a4, sipType_QgsWkbTypes_Type ) );
sipCpp = new sipQgsPoint( QgsPoint( x, y, z, m, wkbType ) );
}

sipCpp = new sipQgsPoint( x, y, z, m, a4 );
% End
#endif

/**
* Construct a QgsPoint from a QgsPointXY object
*/
explicit QgsPoint( const QgsPointXY &p );
explicit QgsPoint( const QgsPointXY &p ) SIP_SKIP;

/**
* Construct a QgsPoint from a QPointF
*/
explicit QgsPoint( QPointF p );
explicit QgsPoint( QPointF p ) SIP_SKIP;

/**
* Create a new point with the given wkbtype and values.
Expand Down
2 changes: 1 addition & 1 deletion tests/src/python/test_qgseditformconfig.py
Expand Up @@ -106,7 +106,7 @@ def testFormUi(self):
app.processEvents()
self.assertEqual(content.status(), QgsFetchedContent.Finished)

# Failing on Travis, seg faut in event loop, no idea why
# Failing on Travis, seg fault in event loop, no idea why
"""
@unittest.expectedFailure
def testFormPy(self):
Expand Down
36 changes: 35 additions & 1 deletion tests/src/python/test_qgspoint.py
Expand Up @@ -12,7 +12,8 @@

import qgis # NOQA

from qgis.core import QgsPointXY
from qgis.core import QgsPointXY, QgsPoint, QgsWkbTypes
from qgis.PyQt.QtCore import QPointF

from qgis.testing import start_app, unittest

Expand Down Expand Up @@ -52,6 +53,39 @@ def test_hash(self):
mySet = set([a, b, c, d, e])
assert len(mySet) == 4

def test_issue_32443(self):
p = QgsPoint()
assert p.wkbType() == QgsWkbTypes.Point and p.x() != p.x() and p.y() != p.y()

# ctor from QgsPointXY should be available
p = QgsPoint(QgsPointXY(1, 2))
assert p.wkbType() == QgsWkbTypes.Point and p.x() == 1 and p.y() == 2

# ctor from QPointF should be available
p = QgsPoint(QPointF(1, 2))
assert p.wkbType() == QgsWkbTypes.Point and p.x() == 1 and p.y() == 2

p = QgsPoint(1, 2)
assert p.wkbType() == QgsWkbTypes.Point and p.x() == 1 and p.y() == 2

p = QgsPoint(1, 2, 3)
assert p.wkbType() == QgsWkbTypes.PointZ and p.x() == 1 and p.y() == 2 and p.z() == 3

p = QgsPoint(1, 2, z=3)
assert p.wkbType() == QgsWkbTypes.PointZ and p.x() == 1 and p.y() == 2 and p.z() == 3

p = QgsPoint(1, 2, m=3)
assert p.wkbType() == QgsWkbTypes.PointM and p.x() == 1 and p.y() == 2 and p.m() == 3

p = QgsPoint(1, 2, wkbType=QgsWkbTypes.PointM)
assert p.wkbType() == QgsWkbTypes.PointM and p.x() == 1 and p.y() == 2 and p.m() != p.m()

p = QgsPoint(1, 2, 3, 4)
assert p.wkbType() == QgsWkbTypes.PointZM and p.x() == 1 and p.y() == 2 and p.z() == 3 and p.m() == 4

p = QgsPoint(1, 2, m=4, z=3)
assert p.wkbType() == QgsWkbTypes.PointZM and p.x() == 1 and p.y() == 2 and p.z() == 3 and p.m() == 4


if __name__ == '__main__':
unittest.main()

0 comments on commit a022ddc

Please sign in to comment.