Coverage Report

Created: 2026-05-16 08:20

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