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

Last change on this file since 193 was 193, checked in by Maciej Komosinski, 6 years ago

Set svn:eol-style native for all textual files

  • Property svn:eol-style set to native
File size: 5.2 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        switch (model.getPart(partIndex)->shape)
100        {
101                case Part::SHAPE_ELLIPSOID:
102                        return externalAreaOfEllipsoid(model, partIndex, density);
103                       
104                case Part::SHAPE_CUBOID:
105                        return externalAreaOfCuboid(model, partIndex, density);
106                       
107                case Part::SHAPE_CYLINDER:
108                        return externalAreaOfCylinder(model, partIndex, density);
109        }
110}
111
112double externalAreaOfSurface(const Model &model, const int partIndex, MeshBuilder::Iterator &surface, const double area)
113{
114        Pt3D point;
115        int all = 0, sur = 0;
116       
117        while (surface.tryGetNext(point))
118        {
119                all += 1;
120                sur += GeometryUtils::isPointInsideModelExcludingPart(point, &model, partIndex) ? 0 : 1;
121        }
122       
123        return sur * area / all;
124}
125
126double ModelGeometryInfo::externalAreaOfEllipsoid(const Model &model, const int partIndex, const double density)
127{
128        Part *part = model.getPart(partIndex);
129       
130        MeshBuilder::EllipsoidSurface ellipsoid(density);
131        ellipsoid.initialize(part);
132       
133        double area = GeometryUtils::ellipsoidArea(part->scale);
134       
135        return externalAreaOfSurface(model, partIndex, ellipsoid, area);
136}
137
138double ModelGeometryInfo::externalAreaOfCuboid(const Model &model, const int partIndex, const double density)
139{
140        Part *part = model.getPart(partIndex);
141       
142        double externalArea = 0.0;
143       
144        MeshBuilder::RectangleSurface rectangle(density);
145       
146        for (CuboidFaces::Face f = CuboidFaces::FIRST; f < CuboidFaces::NUMBER; f = CuboidFaces::Face(f+1))
147        {
148                rectangle.initialize(part, f);
149               
150                double area = 4.0;
151                area *= !CuboidFaces::isX(f) ? part->scale.x : 1.0;
152                area *= !CuboidFaces::isY(f) ? part->scale.y : 1.0;
153                area *= !CuboidFaces::isZ(f) ? part->scale.z : 1.0;
154               
155                externalArea += externalAreaOfSurface(model, partIndex, rectangle, area);
156        }
157       
158        return externalArea;
159}
160
161double ModelGeometryInfo::externalAreaOfCylinder(const Model &model, const int partIndex, const double density)
162{
163        Part *part = model.getPart(partIndex);
164       
165        double externalArea = 0.0;
166       
167        MeshBuilder::EllipseSurface ellipse(density);
168       
169        double area = M_PI * part->scale.y * part->scale.z;
170       
171        for (CylinderBases::Base b = CylinderBases::FIRST; b < CylinderBases::NUMBER; b = CylinderBases::Base(b+1))
172        {
173                ellipse.initialize(part, b);
174               
175                externalArea += externalAreaOfSurface(model, partIndex, ellipse, area);
176        }
177       
178        MeshBuilder::CylinderWallSurface cylinderWall(density);
179        cylinderWall.initialize(part);
180       
181        area = 2.0*part->scale.x * GeometryUtils::ellipsePerimeter(part->scale.y, part->scale.z);
182       
183        externalArea += externalAreaOfSurface(model, partIndex, cylinderWall, area);
184       
185        return externalArea;
186}
Note: See TracBrowser for help on using the repository browser.