source: cpp/frams/model/geometry/modelgeometryinfo.cpp @ 261

Last change on this file since 261 was 261, checked in by Maciej Komosinski, 9 years ago

Verified return values, added error messages [closes #47]

  • Property svn:eol-style set to native
File size: 5.4 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 "modelgeometryinfo.h"
6#include <frams/model/geometry/geometryutils.h>
7#include <frams/model/geometry/meshbuilder.h>
8
9void ModelGeometryInfo::findSizesAndAxesOfModel(const Model &model, const double density,
10        Pt3D &sizes, Orient &axes)
11{
12        SListTempl<Pt3D> points;
13        MeshBuilder::ModelApices apices(density);
14        apices.initialize(&model);
15        apices.addAllPointsToList(points);
16        GeometryUtils::findSizesAndAxesOfPointsGroup(points, sizes, axes);
17}
18
19bool ModelGeometryInfo::boundingBox(const Model &model, Pt3D &lowerBoundary, Pt3D &upperBoundary)
20{
21        if (model.getPartCount() == 0)
22        {
23                return false;
24        }
25       
26        boundingBox(model.getPart(0), lowerBoundary, upperBoundary);
27       
28        for (int i = 1; i < model.getPartCount(); i++)
29        {
30                Pt3D partLowerBoundary, partUpperBoundary;
31                boundingBox(model.getPart(i), partLowerBoundary, partUpperBoundary);
32               
33                lowerBoundary.getMin(partLowerBoundary);
34                upperBoundary.getMax(partUpperBoundary);
35        }
36       
37        return true;
38}
39
40void ModelGeometryInfo::boundingBox(const Part *part, Pt3D &lowerBoundary, Pt3D &upperBoundary)
41{
42        lowerBoundary.x = upperBoundary.x = part->p.x;
43        lowerBoundary.y = upperBoundary.y = part->p.y;
44        lowerBoundary.z = upperBoundary.z = part->p.z;
45       
46        for (Octants::Octant o = Octants::FIRST; o < Octants::NUMBER; o = Octants::Octant(o+1))
47        {
48                Pt3D vertex = part->scale;
49                vertex.x *= Octants::isPositiveX(o) ? +1 : -1;
50                vertex.y *= Octants::isPositiveY(o) ? +1 : -1;
51                vertex.z *= Octants::isPositiveZ(o) ? +1 : -1;
52               
53                vertex = part->o.transform(vertex) + part->p;
54               
55                lowerBoundary.getMin(vertex);
56                upperBoundary.getMax(vertex);
57        }
58}
59
60double ModelGeometryInfo::volume(const Model &model, const double density)
61{
62        Pt3D lowerBoundary, upperBoundary;
63        boundingBox(model, lowerBoundary, upperBoundary);
64       
65        MeshBuilder::BoundingBoxVolume iterator(density);
66        iterator.initialize(lowerBoundary, upperBoundary);
67       
68        Pt3D point;
69        int allPoints = 0, pointsInsideModel = 0;
70       
71        while (iterator.tryGetNext(point))
72        {
73                allPoints += 1;
74                pointsInsideModel += GeometryUtils::isPointInsideModel(point, model) ? 1 : 0;
75        }
76       
77        double boundingBoxVolume
78                = (upperBoundary.x - lowerBoundary.x)
79                * (upperBoundary.y - lowerBoundary.y)
80                * (upperBoundary.z - lowerBoundary.z);
81       
82        return boundingBoxVolume * (double)pointsInsideModel / (double)allPoints;
83}
84
85double ModelGeometryInfo::area(const Model &model, const double density)
86{
87        double area = 0.0;
88       
89        for (int partIndex = 0; partIndex < model.getPartCount(); partIndex+=1)
90        {
91                area += externalAreaOfPart(model, partIndex, density);
92        }
93       
94        return area;
95}
96
97double ModelGeometryInfo::externalAreaOfPart(const Model &model, const int partIndex, const double density)
98{
99        Part *part = model.getPart(partIndex);
100        switch (part->shape)
101        {
102                case Part::SHAPE_ELLIPSOID:
103                        return externalAreaOfEllipsoid(model, partIndex, density);
104                       
105                case Part::SHAPE_CUBOID:
106                        return externalAreaOfCuboid(model, partIndex, density);
107                       
108                case Part::SHAPE_CYLINDER:
109                        return externalAreaOfCylinder(model, partIndex, density);
110        }
111        FMprintf("ModelGeometryInfo", "externalAreaOfPart", FMLV_ERROR, "Part shape=%d not supported", part->shape);
112        return 0;
113}
114
115double externalAreaOfSurface(const Model &model, const int partIndex, MeshBuilder::Iterator &surface, const double area)
116{
117        Pt3D point;
118        int all = 0, sur = 0;
119       
120        while (surface.tryGetNext(point))
121        {
122                all += 1;
123                sur += GeometryUtils::isPointInsideModelExcludingPart(point, &model, partIndex) ? 0 : 1;
124        }
125       
126        return sur * area / all;
127}
128
129double ModelGeometryInfo::externalAreaOfEllipsoid(const Model &model, const int partIndex, const double density)
130{
131        Part *part = model.getPart(partIndex);
132       
133        MeshBuilder::EllipsoidSurface ellipsoid(density);
134        ellipsoid.initialize(part);
135       
136        double area = GeometryUtils::ellipsoidArea(part->scale);
137       
138        return externalAreaOfSurface(model, partIndex, ellipsoid, area);
139}
140
141double ModelGeometryInfo::externalAreaOfCuboid(const Model &model, const int partIndex, const double density)
142{
143        Part *part = model.getPart(partIndex);
144       
145        double externalArea = 0.0;
146       
147        MeshBuilder::RectangleSurface rectangle(density);
148       
149        for (CuboidFaces::Face f = CuboidFaces::FIRST; f < CuboidFaces::NUMBER; f = CuboidFaces::Face(f+1))
150        {
151                rectangle.initialize(part, f);
152               
153                double area = 4.0;
154                area *= !CuboidFaces::isX(f) ? part->scale.x : 1.0;
155                area *= !CuboidFaces::isY(f) ? part->scale.y : 1.0;
156                area *= !CuboidFaces::isZ(f) ? part->scale.z : 1.0;
157               
158                externalArea += externalAreaOfSurface(model, partIndex, rectangle, area);
159        }
160       
161        return externalArea;
162}
163
164double ModelGeometryInfo::externalAreaOfCylinder(const Model &model, const int partIndex, const double density)
165{
166        Part *part = model.getPart(partIndex);
167       
168        double externalArea = 0.0;
169       
170        MeshBuilder::EllipseSurface ellipse(density);
171       
172        double area = M_PI * part->scale.y * part->scale.z;
173       
174        for (CylinderBases::Base b = CylinderBases::FIRST; b < CylinderBases::NUMBER; b = CylinderBases::Base(b+1))
175        {
176                ellipse.initialize(part, b);
177               
178                externalArea += externalAreaOfSurface(model, partIndex, ellipse, area);
179        }
180       
181        MeshBuilder::CylinderWallSurface cylinderWall(density);
182        cylinderWall.initialize(part);
183       
184        area = 2.0*part->scale.x * GeometryUtils::ellipsePerimeter(part->scale.y, part->scale.z);
185       
186        externalArea += externalAreaOfSurface(model, partIndex, cylinderWall, area);
187       
188        return externalArea;
189}
Note: See TracBrowser for help on using the repository browser.