Skip to content

Commit

Permalink
The first point in 3D is used to propagate Z dimension
Browse files Browse the repository at this point in the history
  • Loading branch information
pblottiere committed Feb 16, 2018
1 parent ce9e012 commit 76a57b8
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 79 deletions.
11 changes: 11 additions & 0 deletions python/core/geometry/qgsgeometryutils.sip.in
Expand Up @@ -388,6 +388,17 @@ Return the coefficients (a, b, c for equation "ax + by + c = 0") of a line defin
:return: A line (segment) from p to perpendicular point on segment [s1, s2]
%End

static bool setZValueFromPoints( const QgsPointSequence &points, QgsPoint &point );
%Docstring
A Z dimension is added to ``point`` if one of the point in the list
``points`` is in 3D. Moreover, the Z value of ``point`` is updated with.

:param points: List of points in which a 3D point is searched.
:param point: The point to update with Z dimension and value.

:return: true if the point is updated, false otherwise
%End


};

Expand Down
35 changes: 13 additions & 22 deletions src/core/geometry/qgscircle.cpp
Expand Up @@ -40,6 +40,8 @@ QgsCircle QgsCircle::from2Points( const QgsPoint &pt1, const QgsPoint &pt2 )
double azimuth = QgsGeometryUtils::lineAngle( pt1.x(), pt1.y(), pt2.x(), pt2.y() ) * 180.0 / M_PI;
double radius = pt1.distance( pt2 ) / 2.0;

QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1 << pt2, center );

return QgsCircle( center, radius, azimuth );
}

Expand Down Expand Up @@ -138,26 +140,8 @@ QgsCircle QgsCircle::from3Points( const QgsPoint &pt1, const QgsPoint &pt2, cons
double aSlope = yDelta_a / xDelta_a;
double bSlope = yDelta_b / xDelta_b;

// set z cooridnate for center
double z = std::numeric_limits<double>::quiet_NaN();
if ( p1.is3D() )
{
z = p1.z();
}
else if ( p2.is3D() )
{
z = p2.z();
}
else if ( p3.is3D() )
{
z = p3.z();
}

if ( ! std::isnan( z ) )
{
center.convertTo( QgsWkbTypes::addZ( center.wkbType() ) );
center.setZ( z );
}
// set z coordinate for center
QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << p1 << p2 << p3, center );

if ( ( std::fabs( xDelta_a ) <= epsilon ) && ( std::fabs( yDelta_b ) <= epsilon ) )
{
Expand Down Expand Up @@ -197,7 +181,11 @@ QgsCircle QgsCircle::fromCenterDiameter( const QgsPoint &center, double diameter
QgsCircle QgsCircle::fromCenterPoint( const QgsPoint &center, const QgsPoint &pt1 )
{
double azimuth = QgsGeometryUtils::lineAngle( center.x(), center.y(), pt1.x(), pt1.y() ) * 180.0 / M_PI;
return QgsCircle( center, center.distance( pt1 ), azimuth );

QgsPoint centerPt( center );
QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1, centerPt );

return QgsCircle( centerPt, centerPt.distance( pt1 ), azimuth );
}

QgsCircle QgsCircle::from3Tangents( const QgsPoint &pt1_tg1, const QgsPoint &pt2_tg1, const QgsPoint &pt1_tg2, const QgsPoint &pt2_tg2, const QgsPoint &pt1_tg3, const QgsPoint &pt2_tg3, double epsilon )
Expand Down Expand Up @@ -242,7 +230,10 @@ QgsCircle QgsCircle::fromExtent( const QgsPoint &pt1, const QgsPoint &pt2 )
return QgsCircle();
}

return QgsCircle( QgsGeometryUtils::midpoint( pt1, pt2 ), delta_x / 2.0, 0 );
QgsPoint center = QgsGeometryUtils::midpoint( pt1, pt2 );
QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1 << pt2, center );

return QgsCircle( center, delta_x / 2.0, 0 );
}

double QgsCircle::area() const
Expand Down
14 changes: 12 additions & 2 deletions src/core/geometry/qgsellipse.cpp
Expand Up @@ -57,6 +57,8 @@ QgsEllipse QgsEllipse::fromFoci( const QgsPoint &pt1, const QgsPoint &pt2, const
double axis_a = dist / 2.0;
double axis_b = std::sqrt( std::pow( axis_a, 2.0 ) - std::pow( dist_p1p2 / 2.0, 2.0 ) );

QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1 << pt2 << pt3, center );

return QgsEllipse( center, axis_a, axis_b, azimuth );
}

Expand All @@ -67,6 +69,8 @@ QgsEllipse QgsEllipse::fromExtent( const QgsPoint &pt1, const QgsPoint &pt2 )
double axis_b = std::fabs( pt2.y() - pt1.y() ) / 2.0;
double azimuth = 90.0;

QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1 << pt2, center );

return QgsEllipse( center, axis_a, axis_b, azimuth );
}

Expand All @@ -76,7 +80,10 @@ QgsEllipse QgsEllipse::fromCenterPoint( const QgsPoint &center, const QgsPoint &
double axis_b = std::fabs( pt1.y() - center.y() );
double azimuth = 90.0;

return QgsEllipse( center, axis_a, axis_b, azimuth );
QgsPoint centerPt( center );
QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1, centerPt );

return QgsEllipse( centerPt, axis_a, axis_b, azimuth );
}

QgsEllipse QgsEllipse::fromCenter2Points( const QgsPoint &center, const QgsPoint &pt1, const QgsPoint &pt2 )
Expand All @@ -88,7 +95,10 @@ QgsEllipse QgsEllipse::fromCenter2Points( const QgsPoint &center, const QgsPoint
QgsPoint pp = center.project( length, 90 + azimuth );
double axis_b = center.distance( pp );

return QgsEllipse( center, axis_a, axis_b, azimuth );
QgsPoint centerPt( center );
QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << pt1 << pt2, centerPt );

return QgsEllipse( centerPt, axis_a, axis_b, azimuth );
}

bool QgsEllipse::operator ==( const QgsEllipse &elp ) const
Expand Down
57 changes: 21 additions & 36 deletions src/core/geometry/qgsgeometryutils.cpp
Expand Up @@ -248,22 +248,8 @@ bool QgsGeometryUtils::lineIntersection( const QgsPoint &p1, QgsVector v1, const

intersection = QgsPoint( p1.x() + v1.x() * k, p1.y() + v1.y() * k );

// z support for inter point
double z = std::numeric_limits<double>::quiet_NaN();
if ( p1.is3D() )
{
z = p1.z();
}
else if ( p2.is3D() )
{
z = p2.z();
}

if ( ! std::isnan( z ) )
{
intersection.convertTo( QgsWkbTypes::addZ( intersection.wkbType() ) );
intersection.setZ( z );
}
// z support for intersection point
QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << p1 << p2, intersection );

return true;
}
Expand Down Expand Up @@ -623,26 +609,7 @@ bool QgsGeometryUtils::segmentMidPoint( const QgsPoint &p1, const QgsPoint &p2,
result = possibleMidPoints.at( minDistIndex );

// add z support if necessary
double z = std::numeric_limits<double>::quiet_NaN();

if ( p1.is3D() && p2.is3D() )
{
z = ( p1.z() + p2.z() ) / 2.;
}
else if ( p1.is3D() && !p2.is3D() )
{
z = p1.z();
}
else if ( !p1.is3D() && p2.is3D() )
{
z = p2.z();
}

if ( ! std::isnan( z ) )
{
result.convertTo( QgsWkbTypes::addZ( result.wkbType() ) );
result.setZ( z );
}
QgsGeometryUtils::setZValueFromPoints( QgsPointSequence() << p1 << p2, result );

return true;
}
Expand Down Expand Up @@ -1205,3 +1172,21 @@ double QgsGeometryUtils::averageAngle( double a1, double a2 )
}
return normalizedAngle( resultAngle );
}

bool QgsGeometryUtils::setZValueFromPoints( const QgsPointSequence &points, QgsPoint &point )
{
bool rc = false;

for ( const QgsPoint &pt : points )
{
if ( pt.is3D() )
{
point.convertTo( QgsWkbTypes::addZ( point.wkbType() ) );
point.setZ( pt.z() );
rc = true;
break;
}
}

return rc;
}
10 changes: 10 additions & 0 deletions src/core/geometry/qgsgeometryutils.h
Expand Up @@ -410,6 +410,16 @@ class CORE_EXPORT QgsGeometryUtils
*/
static QgsLineString perpendicularSegment( const QgsPoint &p, const QgsPoint &s1, const QgsPoint &s2 );

/**
* A Z dimension is added to \a point if one of the point in the list
* \a points is in 3D. Moreover, the Z value of \a point is updated with.
*
* \param points List of points in which a 3D point is searched.
* \param point The point to update with Z dimension and value.
* \returns true if the point is updated, false otherwise
*/
static bool setZValueFromPoints( const QgsPointSequence &points, QgsPoint &point );

//! \note not available in Python bindings
enum ComponentType SIP_SKIP
{
Expand Down
23 changes: 4 additions & 19 deletions src/core/geometry/qgstriangle.cpp
Expand Up @@ -574,26 +574,11 @@ QgsPoint QgsTriangle::inscribedCenter() const
l.at( 1 ) * vertexAt( 0 ).y() +
l.at( 2 ) * vertexAt( 1 ).y() ) / perimeter();

double z = std::numeric_limits<double>::quiet_NaN();
if ( vertexAt( 0 ).is3D() )
{
z = vertexAt( 0 ).z();
}
else if ( vertexAt( 1 ).is3D() )
{
z = vertexAt( 1 ).z();
}
else if ( vertexAt( 2 ).is3D() )
{
z = vertexAt( 2 ).z();
}

QgsPoint center( x, y );
if ( !std::isnan( z ) )
{
center.convertTo( QgsWkbTypes::PointZ );
center.setZ( z );
}

QgsPointSequence points;
points << vertexAt( 0 ) << vertexAt( 1 ) << vertexAt( 2 );
QgsGeometryUtils::setZValueFromPoints( points, center );

return center;
}
Expand Down

0 comments on commit 76a57b8

Please sign in to comment.