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

Last change on this file since 1186 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
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
[1111]2// Copyright (C) 1999-2021  Maciej Komosinski and Szymon Ulatowski.
[286]3// See LICENSE.txt for details.
[271]4
[235]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
[242]11static ParamEntry modelgeo_paramtab[] =
[235]12{
[1111]13        { "Creature: Geometry", 1, 6, "ModelGeometry",
[548]14        "Approximately estimates sizes, volume, and area of a Model based on the geometry of its parts.\n"
[242]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"
[548]19        "var mg=ModelGeometry.forModel(GenePools[0][0].getModel()); mg.geom_density=2; GenePools[0][0].data->area=mg.area();\n" },
[1158]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...
[242]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), },
[1115]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)."},
[242]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, },
[235]27};
28#undef FIELDSTRUCT
29
30ExtObject ModelGeometry::makeDynamicObject(ModelGeometry* mg)
[242]31{
32        return ExtObject(&mg->par, mg);
33}
[235]34
35ModelGeometry::ModelGeometry(ModelObj *mo)
[1111]36        :par(modelgeo_paramtab, this)
[235]37{
[242]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();
[235]43}
44
45ModelGeometry::~ModelGeometry()
46{
[242]47        if (model != NULL)
48                model->decref();
[235]49}
50
[242]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()
[235]55{
[242]56        cached_volume = -1;
57        cached_area = -1;
58        cached_sizes.x = -1;
[1111]59        cached_voxels.setEmpty();
[242]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)
[235]67        {
[242]68                invalidateAllCached();
69                cached_for_density = density;
[235]70        }
71}
72
[242]73void ModelGeometry::p_formodel(ExtValue *args, ExtValue *ret)
[235]74{
[242]75        Model *m = ModelObj::fromObject(*args);
76        if (m != NULL)
77        {
[1111]78                if (m->getShapeType() == Model::SHAPETYPE_BALL_AND_STICK)
79                {
[661]80                        Model *converted = new Model;
81                        converted->open();
[1115]82                        converted->buildUsingSolidShapeTypes(*m, Part::SHAPE_CYLINDER);
[661]83                        converted->close();
[1111]84                        m = converted;
85                }
[242]86                ModelGeometry *mg = new ModelGeometry((ModelObj*)m);
87                mg->density = density;
88                ret->setObject(ModelGeometry::makeDynamicObject(mg));
89        }
90        else
91                ret->setEmpty();
[235]92}
93
[242]94void ModelGeometry::p_volume(ExtValue *args, ExtValue *ret)
[235]95{
[242]96        onDensityChanged();
97        if (cached_volume < 0) //calculate if invalid
98                cached_volume = ModelGeometryInfo::volume(*model, density);
99        ret->setDouble(cached_volume);
[235]100}
101
[242]102void ModelGeometry::p_area(ExtValue *args, ExtValue *ret)
[235]103{
[242]104        onDensityChanged();
105        if (cached_area < 0) //calculate if invalid
106                cached_area = ModelGeometryInfo::area(*model, density);
107        ret->setDouble(cached_area);
[235]108}
[242]109
[1111]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
[242]118void ModelGeometry::p_sizesandaxes(ExtValue *args, ExtValue *ret)
119{
120        onDensityChanged();
121        if (cached_sizes.x < 0) //calculate if invalid
[658]122                ModelGeometryInfo::findSizesAndAxes(*model, density, cached_sizes, cached_axes);
[242]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.