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

Last change on this file since 372 was 372, checked in by sz, 9 years ago

Renamed some classes and functions to make their purpose more obvious:

All MessageHandlers? must now be given the explicit "Enable" argument if you want them to automatically become active. This makes side effects clearly visible.

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