File indexing completed on 2024-05-12 03:50:13

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2008 Torsten Rahn <rahn@kde.org>
0004 //
0005 
0006 
0007 #include "GeoDataLinearRing.h"
0008 #include "GeoDataLinearRing_p.h"
0009 
0010 #include "GeoDataTypes.h"
0011 #include "MarbleDebug.h"
0012 
0013 namespace Marble
0014 {
0015 
0016 GeoDataLinearRing::GeoDataLinearRing( TessellationFlags f )
0017     : GeoDataLineString( new GeoDataLinearRingPrivate( f ) )
0018 {
0019 }
0020 
0021 GeoDataLinearRing::GeoDataLinearRing( const GeoDataGeometry & other )
0022   : GeoDataLineString( other )
0023 {
0024 }
0025 
0026 GeoDataLinearRing::~GeoDataLinearRing()
0027 {
0028 }
0029 
0030 const char *GeoDataLinearRing::nodeType() const
0031 {
0032     return GeoDataTypes::GeoDataLinearRingType;
0033 }
0034 
0035 EnumGeometryId GeoDataLinearRing::geometryId() const
0036 {
0037     return GeoDataLinearRingId;
0038 }
0039 
0040 GeoDataGeometry *GeoDataLinearRing::copy() const
0041 {
0042     return new GeoDataLinearRing(*this);
0043 }
0044 
0045 bool GeoDataLinearRing::operator==( const GeoDataLinearRing &other ) const
0046 {
0047     return isClosed() == other.isClosed() &&
0048            GeoDataLineString::operator==( other );
0049 }
0050 
0051 bool GeoDataLinearRing::operator!=( const GeoDataLinearRing &other ) const
0052 {
0053     return !this->operator==(other);
0054 }
0055 
0056 bool GeoDataLinearRing::isClosed() const
0057 {
0058     return true;
0059 }
0060 
0061 qreal GeoDataLinearRing::length( qreal planetRadius, int offset ) const
0062 {
0063     qreal  length = GeoDataLineString::length( planetRadius, offset );
0064 
0065     return length + planetRadius * last().sphericalDistanceTo(first());
0066 }
0067 
0068 bool GeoDataLinearRing::contains( const GeoDataCoordinates &coordinates ) const
0069 {
0070     // Quick bounding box check
0071     if ( !latLonAltBox().contains( coordinates ) ) {
0072         return false;
0073     }
0074 
0075     int const points = size();
0076     bool inside = false; // also true for points = 0
0077     int j = points - 1;
0078 
0079     for ( int i=0; i<points; ++i ) {
0080         GeoDataCoordinates const & one = operator[]( i );
0081         GeoDataCoordinates const & two = operator[]( j );
0082 
0083         if ( ( one.longitude() < coordinates.longitude() && two.longitude() >= coordinates.longitude() ) ||
0084              ( two.longitude() < coordinates.longitude() && one.longitude() >= coordinates.longitude() ) ) {
0085             if ( one.latitude() + ( coordinates.longitude() - one.longitude()) / ( two.longitude() - one.longitude()) * ( two.latitude()-one.latitude() ) < coordinates.latitude() ) {
0086                 inside = !inside;
0087             }
0088         }
0089 
0090         j = i;
0091     }
0092 
0093     return inside;
0094 }
0095 
0096 bool GeoDataLinearRing::isClockwise() const
0097 {
0098     int const n = size();
0099     qreal area = 0;
0100     for ( int i = 1; i < n; ++i ){
0101         area += ( operator[]( i ).longitude() - operator[]( i - 1 ).longitude() ) * ( operator[]( i ).latitude() + operator[]( i - 1 ).latitude() );
0102     }
0103     area += ( operator[]( 0 ).longitude() - operator[]( n - 1 ).longitude() ) * ( operator[] ( 0 ).latitude() + operator[]( n - 1 ).latitude() );
0104 
0105     return area > 0;
0106 }
0107 
0108 }