source: cpp/frams/model/geometry/geometryutils.cpp @ 239

Last change on this file since 239 was 237, checked in by Maciej Komosinski, 10 years ago

Do not use min/max as variable names

  • Property svn:eol-style set to native
File size: 8.5 KB
Line 
1// This file is a part of the Framsticks GDK.
2// Copyright (C) 2002-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5#include "geometryutils.h"
6
7#include <math.h>
8
9double GeometryUtils::pointPosition(const int pointIndex, const int numberOfPoints)
10{
11        return pointIndex / (numberOfPoints-1.0);
12}
13
14double GeometryUtils::pointOnAxis(const double scale, const double position)
15{
16        return (position-0.5) * scale;
17}
18
19double GeometryUtils::pointOnAxis(const double scale, const int pointIndex, const int numberOfPoints)
20{
21        return pointOnAxis(scale, pointPosition(pointIndex, numberOfPoints));
22}
23
24double GeometryUtils::combination(const double value1, const double value2, const double position)
25{
26        return value1 + position * (value2-value1);
27}
28
29double GeometryUtils::combination(const double value1, const double value2, const int pointIndex, const int numberOfPoints)
30{
31        return combination(value1, value2, pointPosition(pointIndex, numberOfPoints));
32}
33
34bool GeometryUtils::isPointInsideModelExcludingPart(const Pt3D &point, const Model *model, const int excludedPartIndex)
35{
36        for (int i = 0; i < excludedPartIndex; i++)
37        {
38                if (isPointInsidePart(point, model->getPart(i)))
39                {
40                        return true;
41                }
42        }
43       
44        for (int i = excludedPartIndex+1; i < model->getPartCount(); i++)
45        {
46                if (isPointStrictlyInsidePart(point, model->getPart(i)))
47                {
48                        return true;
49                }
50        }
51       
52        return false;
53}
54
55bool GeometryUtils::isPointInsideModel(const Pt3D &point, const Model &model)
56{
57        for (int i = 0; i < model.getPartCount(); i++)
58        {
59                if (isPointInsidePart(point, model.getPart(i)))
60                {
61                        return true;
62                }
63        }
64       
65        return false;
66}
67
68bool GeometryUtils::isPointInsidePart(const Pt3D &point, const Part *part)
69{
70        switch (part->shape)
71        {
72                case Part::SHAPE_ELLIPSOID:
73                        return isPointInsideEllipsoid(point, part);
74                        break;
75                       
76                case Part::SHAPE_CUBOID:
77                        return isPointInsideCuboid(point, part);
78                        break;
79                       
80                case Part::SHAPE_CYLINDER:
81                        return isPointInsideCylinder(point, part);
82                        break;
83        }
84        return false;
85}
86
87bool GeometryUtils::isPointStrictlyInsidePart(const Pt3D &point, const Part *part)
88{
89        switch (part->shape)
90        {
91                case Part::SHAPE_ELLIPSOID:
92                        return isPointStrictlyInsideEllipsoid(point, part);
93                        break;
94                       
95                case Part::SHAPE_CUBOID:
96                        return isPointStrictlyInsideCuboid(point, part);
97                        break;
98                       
99                case Part::SHAPE_CYLINDER:
100                        return isPointStrictlyInsideCylinder(point, part);
101                        break;
102        }
103        return false;
104}
105
106bool GeometryUtils::isPointInsideEllipsoid(const Pt3D &point, const Part *part)
107{
108        Pt3D moved = point - part->p;
109        Pt3D rotated;
110        part->o.revTransform(rotated, moved);
111       
112        double r
113                = (pow(rotated.x, 2.0) / pow(part->scale.x, 2.0))
114                + (pow(rotated.y, 2.0) / pow(part->scale.y, 2.0))
115                + (pow(rotated.z, 2.0) / pow(part->scale.z, 2.0));
116       
117        return r <= 1.0;
118}
119
120bool GeometryUtils::isPointStrictlyInsideEllipsoid(const Pt3D &point, const Part *part)
121{
122        Pt3D moved = point - part->p;
123        Pt3D rotated;
124        part->o.revTransform(rotated, moved);
125       
126        double r
127                = (pow(rotated.x, 2.0) / pow(part->scale.x, 2.0))
128                + (pow(rotated.y, 2.0) / pow(part->scale.y, 2.0))
129                + (pow(rotated.z, 2.0) / pow(part->scale.z, 2.0));
130       
131        return r < 1.0;
132}
133
134bool GeometryUtils::isPointInsideCuboid(const Pt3D &point, const Part *part)
135{
136        Pt3D moved = point - part->p;
137        Pt3D rotated;
138        part->o.revTransform(rotated, moved);
139       
140        return (fabs(rotated.x) <= part->scale.x)
141                && (fabs(rotated.y) <= part->scale.y)
142                && (fabs(rotated.z) <= part->scale.z);
143}
144
145bool GeometryUtils::isPointStrictlyInsideCuboid(const Pt3D &point, const Part *part)
146{
147        Pt3D moved = point - part->p;
148        Pt3D rotated;
149        part->o.revTransform(rotated, moved);
150       
151        return (fabs(rotated.x) < part->scale.x)
152                && (fabs(rotated.y) < part->scale.y)
153                && (fabs(rotated.z) < part->scale.z);
154}
155
156bool GeometryUtils::isPointInsideCylinder(const Pt3D &point, const Part *part)
157{
158        Pt3D moved = point - part->p;
159        Pt3D rotated;
160        part->o.revTransform(rotated, moved);
161       
162        double r
163                = (pow(rotated.y, 2.0) / pow(part->scale.y, 2.0))
164                + (pow(rotated.z, 2.0) / pow(part->scale.z, 2.0));
165       
166        return (fabs(rotated.x) <= part->scale.x) && (r <= 1.0);
167}
168
169bool GeometryUtils::isPointStrictlyInsideCylinder(const Pt3D &point, const Part *part)
170{
171        Pt3D moved = point - part->p;
172        Pt3D rotated;
173        part->o.revTransform(rotated, moved);
174       
175        double r
176                = (pow(rotated.y, 2.0) / pow(part->scale.y, 2.0))
177                + (pow(rotated.z, 2.0) / pow(part->scale.z, 2.0));
178       
179        return (fabs(rotated.x) < part->scale.x) && (r < 1.0);
180}
181
182void GeometryUtils::findSizesAndAxesOfPointsGroup(SListTempl<Pt3D> &points, Pt3D &sizes,
183        Orient &axes)
184{
185        findSizeAndAxisOfPointsGroup(points, sizes.x, axes.x);
186        orthographicProjectionToPlane(points, axes.x);
187        findSizeAndAxisOfPointsGroup(points, sizes.y, axes.y);
188        orthographicProjectionToPlane(points, axes.y);
189       
190        Pt3D minimal(points.get(0)), maximal(points.get(0));
191       
192        for (int i = 1; i < points.size(); i++)
193        {
194                minimal.getMin(points.get(i));
195                maximal.getMax(points.get(i));
196        }
197       
198        sizes.z = minimal.distanceTo(maximal);
199        axes.z.vectorProduct(axes.x, axes.y);
200}
201
202void GeometryUtils::findSizeAndAxisOfPointsGroup(const SListTempl<Pt3D> &points, double &size,
203        Pt3D &axis)
204{
205        int index1, index2;
206        size = findTwoFurthestPoints(points, index1, index2);
207        createAxisFromTwoPoints(axis, points.get(index1), points.get(index2));
208}
209
210double GeometryUtils::findTwoFurthestPoints(const SListTempl<Pt3D> &points, int &index1,
211        int &index2)
212{
213        double distance = 0;
214        index1 = index2 = 0;
215       
216        for (int i = 0; i < points.size()-1; i++)
217        {
218                Pt3D p1 = points.get(i);
219               
220                for (int j = i+1; j < points.size(); j++)
221                {
222                        Pt3D p2 = points.get(j);
223                        double d = p1.distanceTo(p2);
224                       
225                        if (d > distance)
226                        {
227                                distance = d;
228                                index1 = i;
229                                index2 = j;
230                        }
231                }
232        }
233       
234        return distance;
235}
236
237void GeometryUtils::createAxisFromTwoPoints(Pt3D &axis, const Pt3D &point1, const Pt3D &point2)
238{
239        Pt3D vector = point2 - point1;
240        vector.normalize();
241       
242        axis.x = vector.x;
243        axis.y = vector.y;
244        axis.z = vector.z;
245}
246
247void GeometryUtils::orthographicProjectionToPlane(SListTempl<Pt3D> &points,
248        const Pt3D &planeNormalVector)
249{
250        for (int i = 0; i < points.size(); i++)
251        {
252                Pt3D &point = points.get(i);
253               
254                double distance = pointDistanceToPlane(point, planeNormalVector);
255               
256                point.x -= planeNormalVector.x * distance;
257                point.y -= planeNormalVector.y * distance;
258                point.z -= planeNormalVector.z * distance;
259        }
260}
261
262double GeometryUtils::pointDistanceToPlane(const Pt3D &point, const Pt3D &planeNormalVector)
263{
264        return planeNormalVector.x*point.x + planeNormalVector.y*point.y + planeNormalVector.z*point.z;
265}
266
267void GeometryUtils::getRectangleApicesFromCuboid(const Part *part, const CuboidFaces::Face face, Pt3D &apex1, Pt3D &apex2, Pt3D &apex3, Pt3D &apex4)
268{
269        Pt3D temp1(part->scale), temp2(part->scale), temp3(part->scale), temp4(part->scale);
270       
271        if (CuboidFaces::isX(face))
272        {
273                temp2.z *= -1;
274                temp3.y *= -1;
275                temp4.z *= -1;
276                temp4.y *= -1;
277        }
278        else if (CuboidFaces::isY(face))
279        {
280                temp2.x *= -1;
281                temp3.z *= -1;
282                temp4.x *= -1;
283                temp4.z *= -1;
284        }
285        else if (CuboidFaces::isZ(face))
286        {
287                temp2.y *= -1;
288                temp3.x *= -1;
289                temp4.y *= -1;
290                temp4.x *= -1;
291        }
292       
293        if (CuboidFaces::isNegative(face))
294        {
295                temp1 *= -1;
296                temp2 *= -1;
297                temp3 *= -1;
298                temp4 *= -1;
299        }
300
301        part->o.transform(apex1, temp1);
302        part->o.transform(apex2, temp2);
303        part->o.transform(apex3, temp3);
304        part->o.transform(apex4, temp4);
305
306        apex1 += part->p;
307        apex2 += part->p;
308        apex3 += part->p;
309        apex4 += part->p;
310}
311
312void GeometryUtils::getRectangleApices(const double width, const double height, const Pt3D &position, const Orient &orient, Pt3D &apex1, Pt3D &apex2, Pt3D &apex3, Pt3D &apex4)
313{
314        Pt3D temp1(0.0, +width, +height);
315        Pt3D temp2(0.0, +width, -height);
316        Pt3D temp3(0.0, -width, +height);
317        Pt3D temp4(0.0, -width, -height);
318
319        orient.transform(apex1, temp1);
320        orient.transform(apex2, temp2);
321        orient.transform(apex3, temp3);
322        orient.transform(apex4, temp4);
323
324        apex1 += position;
325        apex2 += position;
326        apex3 += position;
327        apex4 += position;
328}
329
330void GeometryUtils::getNextEllipseSegmentationPoint(const double d, const double a, const double b, double &x, double &y)
331{
332        x += d / sqrt(1.0 + (b*b * x*x) / (a*a * (a*a - x*x)));
333        y = b * sqrt(1.0 - (x*x) / (a*a));
334}
335
336double GeometryUtils::ellipsoidArea(const Pt3D &sizes)
337{
338        return ellipsoidArea(sizes.x, sizes.y, sizes.z);
339}
340
341double GeometryUtils::ellipsoidArea(const double a, const double b, const double c)
342{
343        double p = 1.6075;
344        double ap = pow(a, p);
345        double bp = pow(b, p);
346        double cp = pow(c, p);
347        return 4*M_PI * pow((ap*bp + bp*cp + cp*ap) / 3.0, 1.0 / p);
348}
349
350double GeometryUtils::ellipsePerimeter(const double a, const double b)
351{
352        return M_PI * ((3 * (a+b)) - sqrt((3*a + b) * (a + 3*b)));
353}
Note: See TracBrowser for help on using the repository browser.