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

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

Added caching of geometry properties (which are costly to compute)

  • Property svn:eol-style set to native
File size: 3.7 KB
Line 
1#include "modelgeoclass.h"
2#include "modelgeometryinfo.h"
3#include <frams/vm/classes/collectionobj.h>
4#include <frams/vm/classes/3dobject.h>
5
6#define FIELDSTRUCT ModelGeometry
7static ParamEntry modelgeo_paramtab[] =
8{
9        { "Creature: Geometry", 1, 5, "ModelGeometry",
10        "Example usage:\n"
11        "Simulator.print(ModelGeometry.forModel(Model.newFromString(\"//0\\np:sh=1\\n\")).area());\n\n"
12        "ModelGeometry.geom_density refers to the global simulator parameter (also available in GUI).\n"
13        "To set geom_density for individual ModelGeometry objects:\n"
14        "var mg=ModelGeometry.forModel(GenePools[0][0].getModel()); mg.geom_density=2; GenePools[0][0].user1=mg.area();\n" },
15        { "geom_density", 0, 0, "Density", "f 0.01 100.0 1.0", FIELD(density), "Affects the geometry calculation precision" }, //note: we used 'geom_density' instead of 'density' to make the name more unique - because sim_params merges all configuration fields in a single namespace.
16        { "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." },
17        { "volume", 0, PARAM_NOSTATIC | PARAM_USERHIDDEN, "volume", "p f()", PROCEDURE(p_volume), },
18        { "area", 0, PARAM_NOSTATIC | PARAM_USERHIDDEN, "area", "p f()", PROCEDURE(p_area), },
19        { "sizesAndAxes", 0, PARAM_NOSTATIC | PARAM_USERHIDDEN, "sizesAndAxes", "p oVector()", PROCEDURE(p_sizesandaxes), "The returned vector contains XYZ (sizes) and Orient (axes) objects." },
20        { 0, 0, 0, },
21};
22#undef FIELDSTRUCT
23
24ExtObject ModelGeometry::makeDynamicObject(ModelGeometry* mg)
25{
26        return ExtObject(&mg->par, mg);
27}
28
29ModelGeometry::ModelGeometry(ModelObj *mo)
30:par(modelgeo_paramtab, this)
31{
32        cached_for_density = -1; //invalid value, will be updated on first request
33        invalidateAllCached();
34        model = mo;
35        if (model != NULL)
36                model->incref();
37}
38
39ModelGeometry::~ModelGeometry()
40{
41        if (model != NULL)
42                model->decref();
43}
44
45// Mark all 3 results as invalid.
46// Validity of these 3 values must be maintained independently,
47// as each of them is calculated by an individual call.
48void ModelGeometry::invalidateAllCached()
49{
50        cached_volume = -1;
51        cached_area = -1;
52        cached_sizes.x = -1;
53}
54
55// Invalidates cached results if a new density is requested
56// (called in all geometry calculation functions)
57void ModelGeometry::onDensityChanged()
58{
59        if (cached_for_density != density)
60        {
61                invalidateAllCached();
62                cached_for_density = density;
63        }
64}
65
66void ModelGeometry::p_formodel(ExtValue *args, ExtValue *ret)
67{
68        Model *m = ModelObj::fromObject(*args);
69        if (m != NULL)
70        {
71                ModelGeometry *mg = new ModelGeometry((ModelObj*)m);
72                mg->density = density;
73                ret->setObject(ModelGeometry::makeDynamicObject(mg));
74        }
75        else
76                ret->setEmpty();
77}
78
79void ModelGeometry::p_volume(ExtValue *args, ExtValue *ret)
80{
81        onDensityChanged();
82        if (cached_volume < 0) //calculate if invalid
83                cached_volume = ModelGeometryInfo::volume(*model, density);
84        ret->setDouble(cached_volume);
85}
86
87void ModelGeometry::p_area(ExtValue *args, ExtValue *ret)
88{
89        onDensityChanged();
90        if (cached_area < 0) //calculate if invalid
91                cached_area = ModelGeometryInfo::area(*model, density);
92        ret->setDouble(cached_area);
93}
94
95void ModelGeometry::p_sizesandaxes(ExtValue *args, ExtValue *ret)
96{
97        onDensityChanged();
98        if (cached_sizes.x < 0) //calculate if invalid
99                ModelGeometryInfo::findSizesAndAxesOfModel(*model, density, cached_sizes, cached_axes);
100
101        VectorObject* n = new VectorObject;
102        n->data += new ExtValue(Pt3D_Ext::makeDynamicObject(cached_sizes));
103        n->data += new ExtValue(Orient_Ext::makeDynamicObject(new Orient_Ext(cached_axes)));
104        ret->setObject(n->makeObject());
105}
Note: See TracBrowser for help on using the repository browser.