Coverage Report

Created: 2026-03-30 09:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrtriangle.cpp
Line
Count
Source
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
2.95k
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
130k
{
74
130k
    OGRLinearRing *poCurve = new OGRLinearRing();
75
130k
    poCurve->addPoint(&p);
76
130k
    poCurve->addPoint(&q);
77
130k
    poCurve->addPoint(&r);
78
130k
    poCurve->addPoint(&p);
79
80
130k
    oCC.addCurveDirectly(this, poCurve, TRUE);
81
130k
}
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
2.95k
{
112
2.95k
    return new (std::nothrow) OGRTriangle(*this);
113
2.95k
}
114
115
/************************************************************************/
116
/*                          getGeometryName()                           */
117
/************************************************************************/
118
119
const char *OGRTriangle::getGeometryName() const
120
8.12k
{
121
8.12k
    return "TRIANGLE";
122
8.12k
}
123
124
/************************************************************************/
125
/*                          getGeometryType()                           */
126
/************************************************************************/
127
128
OGRwkbGeometryType OGRTriangle::getGeometryType() const
129
166k
{
130
166k
    if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED))
131
11.2k
        return wkbTriangleZM;
132
154k
    else if (flags & OGR_G_MEASURED)
133
3.81k
        return wkbTriangleM;
134
151k
    else if (flags & OGR_G_3D)
135
140k
        return wkbTriangleZ;
136
11.0k
    else
137
11.0k
        return wkbTriangle;
138
166k
}
139
140
/************************************************************************/
141
/*                         quickValidityCheck()                         */
142
/************************************************************************/
143
144
bool OGRTriangle::quickValidityCheck() const
145
17.8k
{
146
17.8k
    return oCC.nCurveCount == 0 ||
147
8.75k
           (oCC.nCurveCount == 1 && oCC.papoCurves[0]->getNumPoints() == 4 &&
148
5.21k
            oCC.papoCurves[0]->get_IsClosed());
149
17.8k
}
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
17.9k
{
159
17.9k
    OGRErr eErr = OGRPolygon::importFromWkb(pabyData, nSize, eWkbVariant,
160
17.9k
                                            nBytesConsumedOut);
161
17.9k
    if (eErr != OGRERR_NONE)
162
6.60k
        return eErr;
163
164
11.3k
    if (!quickValidityCheck())
165
1.59k
    {
166
1.59k
        CPLDebug("OGR", "Triangle is not made of a closed rings of 3 points");
167
1.59k
        empty();
168
1.59k
        return OGRERR_CORRUPT_DATA;
169
1.59k
    }
170
171
9.75k
    return OGRERR_NONE;
172
11.3k
}
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
38.1k
{
186
38.1k
    OGRErr eErr = OGRPolygon::importFromWKTListOnly(
187
38.1k
        ppszInput, bHasZ, bHasM, paoPoints, nMaxPoints, padfZ);
188
38.1k
    if (eErr == OGRERR_NONE)
189
6.54k
    {
190
6.54k
        if (!quickValidityCheck())
191
2.60k
        {
192
2.60k
            CPLDebug("OGR",
193
2.60k
                     "Triangle is not made of a closed rings of 3 points");
194
2.60k
            empty();
195
2.60k
            eErr = OGRERR_CORRUPT_DATA;
196
2.60k
        }
197
6.54k
    }
198
199
38.1k
    return eErr;
200
38.1k
}
201
202
/*! @endcond */
203
204
/************************************************************************/
205
/*                          addRingDirectly()                           */
206
/************************************************************************/
207
208
OGRErr OGRTriangle::addRingDirectly(OGRCurve *poNewRing)
209
116
{
210
116
    if (oCC.nCurveCount == 0)
211
116
        return addRingDirectlyInternal(poNewRing, TRUE);
212
0
    else
213
0
        return OGRERR_FAILURE;
214
116
}
215
216
//! @cond Doxygen_Suppress
217
/************************************************************************/
218
/*                         GetCasterToPolygon()                         */
219
/************************************************************************/
220
221
OGRPolygon *OGRTriangle::CasterToPolygon(OGRSurface *poSurface)
222
413
{
223
413
    OGRTriangle *poTriangle = poSurface->toTriangle();
224
413
    OGRPolygon *poRet = new OGRPolygon(*poTriangle);
225
413
    delete poTriangle;
226
413
    return poRet;
227
413
}
228
229
OGRSurfaceCasterToPolygon OGRTriangle::GetCasterToPolygon() const
230
413
{
231
413
    return OGRTriangle::CasterToPolygon;
232
413
}
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