source: cpp/frams/model/geometry/modelgeoclass.cpp @ 1280

Last change on this file since 1280 was 1158, checked in by Maciej Komosinski, 3 years ago

Cosmetic/minor improvements

  • Property svn:eol-style set to native
File size: 4.9 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2021  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#include "modelgeoclass.h"
6#include "modelgeometryinfo.h"
7#include <frams/vm/classes/collectionobj.h>
8#include <frams/vm/classes/3dobject.h>
9
10#define FIELDSTRUCT ModelGeometry
11static ParamEntry modelgeo_paramtab[] =
12{
13        { "Creature: Geometry", 1, 6, "ModelGeometry",
14        "Approximately estimates sizes, volume, and area of a Model based on the geometry of its parts.\n"
15        "Example usage:\n"
16        "Simulator.print(ModelGeometry.forModel(Model.newFromString(\"//0\\np:sh=1\\n\")).area());\n\n"
17        "ModelGeometry.geom_density refers to the global simulator parameter (also available in GUI).\n"
18        "To set geom_density for individual ModelGeometry objects:\n"
19        "var mg=ModelGeometry.forModel(GenePools[0][0].getModel()); mg.geom_density=2; GenePools[0][0].data->area=mg.area();\n" },
20        { "geom_density", 0, 0, "Density", "f 0.01 100.0 3.0", FIELD(density), "The number of samples (per unit length in one dimension) that affects the precision of estimation of geometrical properties." }, //Note #1: we used 'geom_density' instead of 'density' to make the name more unique - because sim_params merges all configuration fields in a single namespace. Note #2: "density" needs better, more interpretable and more reliable parametrization for surface sampling...
21        { "forModel", 0, PARAM_USERHIDDEN, "", "p oModelGeometry(oModel)", PROCEDURE(p_formodel), "The returned ModelGeometry object can be used to calculate geometric properties (volume, area, sizes) of the associated model. The density is copied from the current global ModelGeometry.geom_density on object creation." },
22        { "volume", 0, PARAM_NOSTATIC | PARAM_USERHIDDEN, "volume", "p f()", PROCEDURE(p_volume), },
23        { "area", 0, PARAM_NOSTATIC | PARAM_USERHIDDEN, "area", "p f()", PROCEDURE(p_area), },
24        { "voxels", 0, PARAM_NOSTATIC | PARAM_USERHIDDEN, "voxels", "p oVector()", PROCEDURE(p_voxels), "Returns a Vector of Pt3D objects from a regular 3D grid (sampled according to ModelGeometry.geom_density) that are inside of the Model body (Parts and Joints)."},
25        { "sizesAndAxes", 0, PARAM_NOSTATIC | PARAM_USERHIDDEN, "sizesAndAxes", "p oVector()", PROCEDURE(p_sizesandaxes), "The returned vector contains XYZ (sizes) and Orient (axes) objects." },
26        { 0, 0, 0, },
27};
28#undef FIELDSTRUCT
29
30ExtObject ModelGeometry::makeDynamicObject(ModelGeometry* mg)
31{
32        return ExtObject(&mg->par, mg);
33}
34
35ModelGeometry::ModelGeometry(ModelObj *mo)
36        :par(modelgeo_paramtab, this)
37{
38        cached_for_density = -1; //invalid value, will be updated on first request
39        invalidateAllCached();
40        model = mo;
41        if (model != NULL)
42                model->incref();
43}
44
45ModelGeometry::~ModelGeometry()
46{
47        if (model != NULL)
48                model->decref();
49}
50
51// Mark all 3 results as invalid.
52// Validity of these 3 values must be maintained independently,
53// as each of them is calculated by an individual call.
54void ModelGeometry::invalidateAllCached()
55{
56        cached_volume = -1;
57        cached_area = -1;
58        cached_sizes.x = -1;
59        cached_voxels.setEmpty();
60}
61
62// Invalidates cached results if a new density is requested
63// (called in all geometry calculation functions)
64void ModelGeometry::onDensityChanged()
65{
66        if (cached_for_density != density)
67        {
68                invalidateAllCached();
69                cached_for_density = density;
70        }
71}
72
73void ModelGeometry::p_formodel(ExtValue *args, ExtValue *ret)
74{
75        Model *m = ModelObj::fromObject(*args);
76        if (m != NULL)
77        {
78                if (m->getShapeType() == Model::SHAPETYPE_BALL_AND_STICK)
79                {
80                        Model *converted = new Model;
81                        converted->open();
82                        converted->buildUsingSolidShapeTypes(*m, Part::SHAPE_CYLINDER);
83                        converted->close();
84                        m = converted;
85                }
86                ModelGeometry *mg = new ModelGeometry((ModelObj*)m);
87                mg->density = density;
88                ret->setObject(ModelGeometry::makeDynamicObject(mg));
89        }
90        else
91                ret->setEmpty();
92}
93
94void ModelGeometry::p_volume(ExtValue *args, ExtValue *ret)
95{
96        onDensityChanged();
97        if (cached_volume < 0) //calculate if invalid
98                cached_volume = ModelGeometryInfo::volume(*model, density);
99        ret->setDouble(cached_volume);
100}
101
102void ModelGeometry::p_area(ExtValue *args, ExtValue *ret)
103{
104        onDensityChanged();
105        if (cached_area < 0) //calculate if invalid
106                cached_area = ModelGeometryInfo::area(*model, density);
107        ret->setDouble(cached_area);
108}
109
110void ModelGeometry::p_voxels(ExtValue *args, ExtValue *ret)
111{
112        onDensityChanged();
113        if (cached_voxels.isEmpty()) //calculate if invalid
114                cached_voxels = ModelGeometryInfo::getVoxels(*model, density);
115        ret->setObject(cached_voxels);
116}
117
118void ModelGeometry::p_sizesandaxes(ExtValue *args, ExtValue *ret)
119{
120        onDensityChanged();
121        if (cached_sizes.x < 0) //calculate if invalid
122                ModelGeometryInfo::findSizesAndAxes(*model, density, cached_sizes, cached_axes);
123
124        VectorObject* n = new VectorObject;
125        n->data += new ExtValue(Pt3D_Ext::makeDynamicObject(cached_sizes));
126        n->data += new ExtValue(Orient_Ext::makeDynamicObject(new Orient_Ext(cached_axes)));
127        ret->setObject(n->makeObject());
128}
Note: See TracBrowser for help on using the repository browser.