Coverage Report

Created: 2025-08-11 09:23

/src/gdal/ogr/ogrtriangle.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  The OGRTriangle geometry class.
5
 * Author:   Avyav Kumar Singh <avyavkumar at gmail dot com>
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2016, Avyav Kumar Singh <avyavkumar at gmail dot com>
9
 * Copyright (c) 2016, Even Rouault <even.roauult at spatialys.com>
10
 *
11
 * SPDX-License-Identifier: MIT
12
 ****************************************************************************/
13
14
#include "ogr_geometry.h"
15
#include "ogr_api.h"
16
#include "cpl_error.h"
17
18
/************************************************************************/
19
/*                             OGRTriangle()                            */
20
/************************************************************************/
21
22
/**
23
 * \brief Copy constructor.
24
 *
25
 */
26
27
69
OGRTriangle::OGRTriangle(const OGRTriangle &) = default;
28
29
/************************************************************************/
30
/*                             OGRTriangle()                            */
31
/************************************************************************/
32
33
/**
34
 * \brief Constructs an OGRTriangle from a valid OGRPolygon. In case of error,
35
 * NULL is returned.
36
 *
37
 * @param other the Polygon we wish to construct a triangle from
38
 * @param eErr encapsulates an error code; contains OGRERR_NONE if the triangle
39
 * is constructed successfully
40
 */
41
42
OGRTriangle::OGRTriangle(const OGRPolygon &other, OGRErr &eErr)
43
0
{
44
    // In case of Polygon, we have to check that it is a valid triangle -
45
    // closed and contains one external ring of four points
46
    // If not, then eErr will contain the error description
47
0
    const OGRCurve *poCurve = other.getExteriorRingCurve();
48
0
    if (other.getNumInteriorRings() == 0 && poCurve != nullptr &&
49
0
        poCurve->get_IsClosed() && poCurve->getNumPoints() == 4)
50
0
    {
51
        // everything is fine
52
0
        eErr = addRing(const_cast<OGRCurve *>(poCurve));
53
0
        if (eErr != OGRERR_NONE)
54
0
            CPLError(CE_Failure, CPLE_NotSupported, "Invalid Triangle");
55
0
    }
56
0
    assignSpatialReference(other.getSpatialReference());
57
0
}
58
59
/************************************************************************/
60
/*                             OGRTriangle()                            */
61
/************************************************************************/
62
63
/**
64
 * \brief Construct a triangle from points
65
 *
66
 * @param p Point 1
67
 * @param q Point 2
68
 * @param r Point 3
69
 */
70
71
OGRTriangle::OGRTriangle(const OGRPoint &p, const OGRPoint &q,
72
                         const OGRPoint &r)
73
163k
{
74
163k
    OGRLinearRing *poCurve = new OGRLinearRing();
75
163k
    poCurve->addPoint(&p);
76
163k
    poCurve->addPoint(&q);
77
163k
    poCurve->addPoint(&r);
78
163k
    poCurve->addPoint(&p);
79
80
163k
    oCC.addCurveDirectly(this, poCurve, TRUE);
81
163k
}
82
83
/************************************************************************/
84
/*                    operator=( const OGRGeometry&)                    */
85
/************************************************************************/
86
87
/**
88
 * \brief Assignment operator
89
 *
90
 * @param other A triangle passed as a parameter
91
 *
92
 * @return OGRTriangle A copy of other
93
 *
94
 */
95
96
OGRTriangle &OGRTriangle::operator=(const OGRTriangle &other)
97
0
{
98
0
    if (this != &other)
99
0
    {
100
0
        OGRPolygon::operator=(other);
101
0
    }
102
0
    return *this;
103
0
}
104
105
/************************************************************************/
106
/*                               clone()                                */
107
/************************************************************************/
108
109
OGRTriangle *OGRTriangle::clone() const
110
111
69
{
112
69
    return new (std::nothrow) OGRTriangle(*this);
113
69
}
114
115
/************************************************************************/
116
/*                          getGeometryName()                           */
117
/************************************************************************/
118
119
const char *OGRTriangle::getGeometryName() const
120
10.4k
{
121
10.4k
    return "TRIANGLE";
122
10.4k
}
123
124
/************************************************************************/
125
/*                          getGeometryType()                           */
126
/************************************************************************/
127
128
OGRwkbGeometryType OGRTriangle::getGeometryType() const
129
200k
{
130
200k
    if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED))
131
13.3k
        return wkbTriangleZM;
132
187k
    else if (flags & OGR_G_MEASURED)
133
4.75k
        return wkbTriangleM;
134
182k
    else if (flags & OGR_G_3D)
135
172k
        return wkbTriangleZ;
136
10.5k
    else
137
10.5k
        return wkbTriangle;
138
200k
}
139
140
/************************************************************************/
141
/*                        quickValidityCheck()                          */
142
/************************************************************************/
143
144
bool OGRTriangle::quickValidityCheck() const
145
29.9k
{
146
29.9k
    return oCC.nCurveCount == 0 ||
147
29.9k
           (oCC.nCurveCount == 1 && oCC.papoCurves[0]->getNumPoints() == 4 &&
148
19.9k
            oCC.papoCurves[0]->get_IsClosed());
149
29.9k
}
150
151
/************************************************************************/
152
/*                           importFromWkb()                            */
153
/************************************************************************/
154
155
OGRErr OGRTriangle::importFromWkb(const unsigned char *pabyData, size_t nSize,
156
                                  OGRwkbVariant eWkbVariant,
157
                                  size_t &nBytesConsumedOut)
158
25.9k
{
159
25.9k
    OGRErr eErr = OGRPolygon::importFromWkb(pabyData, nSize, eWkbVariant,
160
25.9k
                                            nBytesConsumedOut);
161
25.9k
    if (eErr != OGRERR_NONE)
162
11.9k
        return eErr;
163
164
14.0k
    if (!quickValidityCheck())
165
3.33k
    {
166
3.33k
        CPLDebug("OGR", "Triangle is not made of a closed rings of 3 points");
167
3.33k
        empty();
168
3.33k
        return OGRERR_CORRUPT_DATA;
169
3.33k
    }
170
171
10.6k
    return OGRERR_NONE;
172
14.0k
}
173
174
/*! @cond Doxygen_Suppress */
175
/************************************************************************/
176
/*                        importFromWKTListOnly()                       */
177
/*                                                                      */
178
/*      Instantiate from "((x y, x y, ...),(x y, ...),...)"             */
179
/************************************************************************/
180
181
OGRErr OGRTriangle::importFromWKTListOnly(const char **ppszInput, int bHasZ,
182
                                          int bHasM, OGRRawPoint *&paoPoints,
183
                                          int &nMaxPoints, double *&padfZ)
184
185
94.4k
{
186
94.4k
    OGRErr eErr = OGRPolygon::importFromWKTListOnly(
187
94.4k
        ppszInput, bHasZ, bHasM, paoPoints, nMaxPoints, padfZ);
188
94.4k
    if (eErr == OGRERR_NONE)
189
15.9k
    {
190
15.9k
        if (!quickValidityCheck())
191
11.1k
        {
192
11.1k
            CPLDebug("OGR",
193
11.1k
                     "Triangle is not made of a closed rings of 3 points");
194
11.1k
            empty();
195
11.1k
            eErr = OGRERR_CORRUPT_DATA;
196
11.1k
        }
197
15.9k
    }
198
199
94.4k
    return eErr;
200
94.4k
}
201
202
/*! @endcond */
203
204
/************************************************************************/
205
/*                           addRingDirectly()                          */
206
/************************************************************************/
207
208
OGRErr OGRTriangle::addRingDirectly(OGRCurve *poNewRing)
209
45
{
210
45
    if (oCC.nCurveCount == 0)
211
45
        return addRingDirectlyInternal(poNewRing, TRUE);
212
0
    else
213
0
        return OGRERR_FAILURE;
214
45
}
215
216
//! @cond Doxygen_Suppress
217
/************************************************************************/
218
/*                      GetCasterToPolygon()                            */
219
/************************************************************************/
220
221
OGRPolygon *OGRTriangle::CasterToPolygon(OGRSurface *poSurface)
222
0
{
223
0
    OGRTriangle *poTriangle = poSurface->toTriangle();
224
0
    OGRPolygon *poRet = new OGRPolygon(*poTriangle);
225
0
    delete poTriangle;
226
0
    return poRet;
227
0
}
228
229
OGRSurfaceCasterToPolygon OGRTriangle::GetCasterToPolygon() const
230
0
{
231
0
    return OGRTriangle::CasterToPolygon;
232
0
}
233
234
/************************************************************************/
235
/*                        CastToPolygon()                               */
236
/************************************************************************/
237
238
OGRGeometry *OGRTriangle::CastToPolygon(OGRGeometry *poGeom)
239
0
{
240
0
    OGRGeometry *poRet = new OGRPolygon(*(poGeom->toPolygon()));
241
0
    delete poGeom;
242
0
    return poRet;
243
0
}
244
245
//! @endcond