/src/geos/include/geos/operation/intersection/Rectangle.h
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************** |
2 | | * |
3 | | * GEOS - Geometry Engine Open Source |
4 | | * http://geos.osgeo.org |
5 | | * |
6 | | * Copyright (C) 2014 Mika Heiskanen <mika.heiskanen@fmi.fi> |
7 | | * |
8 | | * This is free software; you can redistribute and/or modify it under |
9 | | * the terms of the GNU Lesser General Public Licence as published |
10 | | * by the Free Software Foundation. |
11 | | * See the COPYING file for more information. |
12 | | * |
13 | | **********************************************************************/ |
14 | | |
15 | | #pragma once |
16 | | |
17 | | #include <geos/export.h> |
18 | | |
19 | | #ifdef _MSC_VER |
20 | | #pragma warning(push) |
21 | | #pragma warning(disable: 4251) // warning C4251: needs to have dll-interface to be used by clients of class |
22 | | #endif |
23 | | |
24 | | // Forward declarations |
25 | | namespace geos { |
26 | | namespace geom { |
27 | | class GeometryFactory; |
28 | | class Geometry; |
29 | | class Polygon; |
30 | | class LinearRing; |
31 | | } |
32 | | } |
33 | | |
34 | | namespace geos { |
35 | | namespace operation { // geos::operation |
36 | | namespace intersection { // geos::operation::intersection |
37 | | |
38 | | /** |
39 | | * \brief Clipping rectangle |
40 | | * |
41 | | * A clipping rectangle defines the boundaries of the rectangle |
42 | | * by defining the limiting x- and y-coordinates. The clipping |
43 | | * rectangle must be non-empty. In addition, methods are provided |
44 | | * for specifying the location of a given coordinate with respect |
45 | | * to the clipping rectangle similarly to the Cohen-Sutherland |
46 | | * clipping algorithm. |
47 | | * |
48 | | */ |
49 | | |
50 | | class GEOS_DLL Rectangle { |
51 | | public: |
52 | | |
53 | | /** |
54 | | * \brief Construct a clipping rectangle |
55 | | * |
56 | | * @param x1 x-coordinate of the left edge |
57 | | * @param y1 y-coordinate of the bottom edge |
58 | | * @param x2 x-coordinate of the right edge |
59 | | * @param y2 y-coordinate of the right edge |
60 | | * @throws IllegalArgumentException if the rectangle is empty |
61 | | */ |
62 | | |
63 | | Rectangle(double x1, double y1, double x2, double y2); |
64 | | |
65 | | /** |
66 | | * @return the minimum x-coordinate of the rectangle |
67 | | */ |
68 | | double |
69 | | xmin() const |
70 | 0 | { |
71 | 0 | return xMin; |
72 | 0 | } |
73 | | |
74 | | /** |
75 | | * @return the minimum y-coordinate of the rectangle |
76 | | */ |
77 | | |
78 | | double |
79 | | ymin() const |
80 | 0 | { |
81 | 0 | return yMin; |
82 | 0 | } |
83 | | |
84 | | |
85 | | /** |
86 | | * @return the maximum x-coordinate of the rectangle |
87 | | */ |
88 | | |
89 | | double |
90 | | xmax() const |
91 | 0 | { |
92 | 0 | return xMax; |
93 | 0 | } |
94 | | |
95 | | |
96 | | /** |
97 | | * @return the maximum y-coordinate of the rectangle |
98 | | */ |
99 | | |
100 | | double |
101 | | ymax() const |
102 | 0 | { |
103 | 0 | return yMax; |
104 | 0 | } |
105 | | |
106 | | /** |
107 | | * @return the rectangle as a polygon geometry |
108 | | * |
109 | | * @note Ownership transferred to caller |
110 | | */ |
111 | | geom::Polygon* toPolygon(const geom::GeometryFactory& f) const; |
112 | | |
113 | | geom::LinearRing* toLinearRing(const geom::GeometryFactory& f) const; |
114 | | |
115 | | /** |
116 | | * @brief Position with respect to a clipping rectangle |
117 | | */ |
118 | | |
119 | | enum Position { |
120 | | Inside = 1, |
121 | | Outside = 2, |
122 | | |
123 | | Left = 4, |
124 | | Top = 8, |
125 | | Right = 16, |
126 | | Bottom = 32, |
127 | | |
128 | | TopLeft = Top | Left, // 12 |
129 | | TopRight = Top | Right, // 24 |
130 | | BottomLeft = Bottom | Left, // 36 |
131 | | BottomRight = Bottom | Right // 48 |
132 | | }; |
133 | | |
134 | | /** |
135 | | * @brief Test if the given position is on a Rectangle edge |
136 | | * @param pos Rectangle::Position |
137 | | * @return `true`, if the position is on an edge |
138 | | */ |
139 | | |
140 | | static bool |
141 | | onEdge(Position pos) |
142 | 0 | { |
143 | 0 | return (pos > Outside); |
144 | 0 | } |
145 | | |
146 | | /** |
147 | | * @brief Test if the given positions are on the same Rectangle edge |
148 | | * @param pos1 [Position](@ref Rectangle::Position) of first coordinate |
149 | | * @param pos2 [Position](@ref Rectangle::Position) of second coordinate |
150 | | * @return `true`, if the positions are on the same edge |
151 | | */ |
152 | | |
153 | | static bool |
154 | | onSameEdge(Position pos1, Position pos2) |
155 | 0 | { |
156 | 0 | return onEdge(Position(pos1 & pos2)); |
157 | 0 | } |
158 | | |
159 | | /** |
160 | | * @brief Establish position of coordinate with respect to a Rectangle |
161 | | * @param x x-coordinate |
162 | | * @param y y-coordinate |
163 | | * @return [Position](@ref Rectangle::Position) of the coordinate |
164 | | */ |
165 | | |
166 | | Position |
167 | | position(double x, double y) const |
168 | 0 | { |
169 | | // We assume the point to be inside and test it first |
170 | 0 | if(x > xMin && x < xMax && y > yMin && y < yMax) { |
171 | 0 | return Inside; |
172 | 0 | } |
173 | | // Next we assume the point to be outside and test it next |
174 | 0 | if(x < xMin || x > xMax || y < yMin || y > yMax) { |
175 | 0 | return Outside; |
176 | 0 | } |
177 | | // Slower cases |
178 | 0 | unsigned int pos = 0; |
179 | 0 | if(x == xMin) { |
180 | 0 | pos |= Left; |
181 | 0 | } |
182 | 0 | else if(x == xMax) { |
183 | 0 | pos |= Right; |
184 | 0 | } |
185 | 0 | if(y == yMin) { |
186 | 0 | pos |= Bottom; |
187 | 0 | } |
188 | 0 | else if(y == yMax) { |
189 | 0 | pos |= Top; |
190 | 0 | } |
191 | 0 | return Position(pos); |
192 | 0 | } |
193 | | |
194 | | /** |
195 | | * @brief Next edge in clock-wise direction |
196 | | * @param pos [Position](@ref Rectangle::Position) |
197 | | * @return next [Position](@ref Rectangle::Position) in clock-wise direction |
198 | | */ |
199 | | |
200 | | static Position |
201 | | nextEdge(Position pos) |
202 | 0 | { |
203 | 0 | switch(pos) { |
204 | 0 | case BottomLeft: |
205 | 0 | case Left: |
206 | 0 | return Top; |
207 | 0 | case TopLeft: |
208 | 0 | case Top: |
209 | 0 | return Right; |
210 | 0 | case TopRight: |
211 | 0 | case Right: |
212 | 0 | return Bottom; |
213 | 0 | case BottomRight: |
214 | 0 | case Bottom: |
215 | 0 | return Left; |
216 | | /* silences compiler warnings, Inside & Outside are not handled explicitly */ |
217 | 0 | default: |
218 | 0 | return pos; |
219 | 0 | } |
220 | 0 | } |
221 | | |
222 | | private: |
223 | | |
224 | | Rectangle(); |
225 | | double xMin; |
226 | | double yMin; |
227 | | double xMax; |
228 | | double yMax; |
229 | | |
230 | | }; // class RectangleIntersection |
231 | | |
232 | | } // namespace geos::operation::intersection |
233 | | } // namespace geos::operation |
234 | | } // namespace geos |
235 | | |