/src/geos/src/geom/Triangle.cpp
Line | Count | Source |
1 | | /********************************************************************** |
2 | | * |
3 | | * GEOS - Geometry Engine Open Source |
4 | | * http://geos.osgeo.org |
5 | | * |
6 | | * Copyright (C) 2001-2002 Vivid Solutions Inc. |
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 | | #include <geos/geom/Triangle.h> |
16 | | #include <geos/geom/Coordinate.h> |
17 | | #include <geos/algorithm/CGAlgorithmsDD.h> |
18 | | #include <geos/algorithm/Orientation.h> |
19 | | #include <geos/algorithm/Angle.h> |
20 | | |
21 | | using geos::algorithm::Angle; |
22 | | using geos::algorithm::Orientation; |
23 | | |
24 | | namespace geos { |
25 | | namespace geom { // geos::geom |
26 | | |
27 | | |
28 | | bool |
29 | | Triangle::isIsoceles() |
30 | 0 | { |
31 | 0 | double len0 = p1.distance(p2); |
32 | 0 | double len1 = p0.distance(p2); |
33 | 0 | double len2 = p0.distance(p1); |
34 | 0 | if (len0 == len1 || len1 == len2 || len2 == len0) |
35 | 0 | return true; |
36 | 0 | else |
37 | 0 | return false; |
38 | 0 | } |
39 | | |
40 | | void |
41 | | Triangle::inCentre(CoordinateXY& result) |
42 | 0 | { |
43 | | // the lengths of the sides, labelled by their opposite vertex |
44 | 0 | double len0 = p1.distance(p2); |
45 | 0 | double len1 = p0.distance(p2); |
46 | 0 | double len2 = p0.distance(p1); |
47 | 0 | double circum = len0 + len1 + len2; |
48 | 0 | double inCentreX = (len0 * p0.x + len1 * p1.x + len2 * p2.x) / circum; |
49 | 0 | double inCentreY = (len0 * p0.y + len1 * p1.y + len2 * p2.y) / circum; |
50 | |
|
51 | 0 | result = CoordinateXY(inCentreX, inCentreY); |
52 | 0 | } |
53 | | |
54 | | |
55 | | CoordinateXY |
56 | | Triangle::inCentre(const CoordinateXY& p0, |
57 | | const CoordinateXY& p1, |
58 | | const CoordinateXY& p2) |
59 | 0 | { |
60 | 0 | Triangle tri(p0, p1, p2); |
61 | 0 | CoordinateXY result; |
62 | 0 | tri.inCentre(result); |
63 | 0 | return result; |
64 | 0 | } |
65 | | |
66 | | |
67 | | void |
68 | | Triangle::circumcentre(CoordinateXY& result) |
69 | 0 | { |
70 | 0 | double cx = p2.x; |
71 | 0 | double cy = p2.y; |
72 | 0 | double ax = p0.x - cx; |
73 | 0 | double ay = p0.y - cy; |
74 | 0 | double bx = p1.x - cx; |
75 | 0 | double by = p1.y - cy; |
76 | |
|
77 | 0 | double denom = 2 * det(ax, ay, bx, by); |
78 | 0 | double numx = det(ay, ax * ax + ay * ay, by, bx * bx + by * by); |
79 | 0 | double numy = det(ax, ax * ax + ay * ay, bx, bx * bx + by * by); |
80 | |
|
81 | 0 | double ccx = cx - numx / denom; |
82 | 0 | double ccy = cy + numy / denom; |
83 | |
|
84 | 0 | result = CoordinateXY(ccx, ccy); |
85 | 0 | } |
86 | | |
87 | | |
88 | | double |
89 | | Triangle::circumradius( |
90 | | const CoordinateXY& a, |
91 | | const CoordinateXY& b, |
92 | | const CoordinateXY& c) |
93 | 0 | { |
94 | 0 | double A = a.distance(b); |
95 | 0 | double B = b.distance(c); |
96 | 0 | double C = c.distance(a); |
97 | 0 | double triArea = area(a, b, c); |
98 | 0 | if (triArea == 0.0) |
99 | 0 | return std::numeric_limits<double>::infinity(); |
100 | | |
101 | 0 | return (A * B * C) / (4 * triArea); |
102 | 0 | } |
103 | | |
104 | | |
105 | | void |
106 | | Triangle::circumcentreDD(CoordinateXY& result) |
107 | 0 | { |
108 | 0 | result = algorithm::CGAlgorithmsDD::circumcentreDD(p0, p1, p2); |
109 | 0 | } |
110 | | |
111 | | /* public static */ |
112 | | const CoordinateXY |
113 | | Triangle::circumcentre(const CoordinateXY& p0, const CoordinateXY& p1, const CoordinateXY& p2) |
114 | 0 | { |
115 | 0 | Triangle t(p0, p1, p2); |
116 | 0 | CoordinateXY c; |
117 | 0 | t.circumcentre(c); |
118 | 0 | return c; |
119 | 0 | } |
120 | | |
121 | | /* private */ |
122 | | double |
123 | | Triangle::det(double m00, double m01, double m10, double m11) const |
124 | 0 | { |
125 | 0 | return m00 * m11 - m01 * m10; |
126 | 0 | } |
127 | | |
128 | | |
129 | | /* public static */ |
130 | | bool |
131 | | Triangle::isAcute(const CoordinateXY& a, const CoordinateXY& b, const CoordinateXY& c) |
132 | 0 | { |
133 | 0 | if (!Angle::isAcute(a, b, c)) |
134 | 0 | return false; |
135 | 0 | if (!Angle::isAcute(b, c, a)) |
136 | 0 | return false; |
137 | 0 | if (!Angle::isAcute(c, a, b)) |
138 | 0 | return false; |
139 | 0 | return true; |
140 | 0 | } |
141 | | |
142 | | |
143 | | /* public static */ |
144 | | bool |
145 | | Triangle::isCCW(const CoordinateXY& a, const CoordinateXY& b, const CoordinateXY& c) |
146 | 0 | { |
147 | 0 | return Orientation::COUNTERCLOCKWISE == Orientation::index(a, b, c); |
148 | 0 | } |
149 | | |
150 | | |
151 | | /* public static */ |
152 | | bool |
153 | | Triangle::intersects(const CoordinateXY& a, const CoordinateXY& b, const CoordinateXY& c, const CoordinateXY& p) |
154 | 0 | { |
155 | 0 | int exteriorIndex = isCCW(a, b, c) ? |
156 | 0 | Orientation::CLOCKWISE : Orientation::COUNTERCLOCKWISE; |
157 | 0 | if (exteriorIndex == Orientation::index(a, b, p)) |
158 | 0 | return false; |
159 | 0 | if (exteriorIndex == Orientation::index(b, c, p)) |
160 | 0 | return false; |
161 | 0 | if (exteriorIndex == Orientation::index(c, a, p)) |
162 | 0 | return false; |
163 | 0 | return true; |
164 | 0 | } |
165 | | |
166 | | |
167 | | /* public static */ |
168 | | double |
169 | | Triangle::length(const CoordinateXY& a, const CoordinateXY& b, const CoordinateXY& c) |
170 | 0 | { |
171 | 0 | return a.distance(b) + b.distance(c) + c.distance(a); |
172 | 0 | } |
173 | | |
174 | | /* public */ |
175 | | double |
176 | | Triangle::length() const |
177 | 0 | { |
178 | 0 | return length(p0, p1, p2); |
179 | 0 | } |
180 | | |
181 | | /* public static */ |
182 | | double |
183 | | Triangle::area(const CoordinateXY& a, const CoordinateXY& b, const CoordinateXY& c) |
184 | 0 | { |
185 | 0 | return std::abs(((c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y)) / 2); |
186 | 0 | } |
187 | | |
188 | | /* public */ |
189 | | double |
190 | | Triangle::area() const |
191 | 0 | { |
192 | 0 | return area(p0, p1, p2); |
193 | 0 | } |
194 | | |
195 | | /* public static */ |
196 | | double |
197 | | Triangle::longestSideLength(const CoordinateXY& a, const CoordinateXY& b, const CoordinateXY& c) |
198 | 0 | { |
199 | 0 | double lenAB = a.distance(b); |
200 | 0 | double lenBC = b.distance(c); |
201 | 0 | double lenCA = c.distance(a); |
202 | 0 | double maxLen = lenAB; |
203 | 0 | if (lenBC > maxLen) |
204 | 0 | maxLen = lenBC; |
205 | 0 | if (lenCA > maxLen) |
206 | 0 | maxLen = lenCA; |
207 | 0 | return maxLen; |
208 | 0 | } |
209 | | |
210 | | |
211 | | |
212 | | } // namespace geos::geom |
213 | | } // namespace geos |