Changeset 242 for cpp/frams/model


Ignore:
Timestamp:
05/07/14 20:41:18 (11 years ago)
Author:
Maciej Komosinski
Message:

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

Location:
cpp/frams/model/geometry
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/model/geometry/modelgeoclass.cpp

    r235 r242  
    55
    66#define FIELDSTRUCT ModelGeometry
    7 static ParamEntry modelgeo_paramtab[]=
     7static ParamEntry modelgeo_paramtab[] =
    88{
    9  {"Creature: Geometry",1,5,"ModelGeometry",
    10   "Example usage:\n"
    11   "Simulator.print(ModelGeometry.forModel(Model.newFromString(\"//0\\np:sh=1\\n\")).area());\n"
    12   "ModelGeometry.geodensity refers to the global simulator parameter (also available in GUI).\n"
    13   "Local geodensity of individual ModelGeometry objects can also be changed, like this:\n"
    14   "var mg=ModelGeometry.forModel(GenePools[0][0].getModel()); mg.geodensity=2; GenePools[0][0].user1=mg.area();\n"},
    15  {"geodensity",0,0,"Density","f 0.01 100.0 1.0",FIELD(density),"Affects the geometry calculation precision"}, //note: geodensity instead of density to make the name more unique - because of the unfortunate sim_params merging 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 of the associated model (volume, area, sizes). The density is copied from the current global ModelGeometry.geodensity 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 
    21 {0,0,0,},
     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, },
    2221};
    2322#undef FIELDSTRUCT
    2423
    2524ExtObject ModelGeometry::makeDynamicObject(ModelGeometry* mg)
    26 {return ExtObject(&mg->par,mg);}
     25{
     26        return ExtObject(&mg->par, mg);
     27}
    2728
    2829ModelGeometry::ModelGeometry(ModelObj *mo)
    29         :par(modelgeo_paramtab,this)
     30:par(modelgeo_paramtab, this)
    3031{
    31 model=mo;
    32 if (model!=NULL)
    33         model->incref();
     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();
    3437}
    3538
    3639ModelGeometry::~ModelGeometry()
    3740{
    38 if (model!=NULL)
    39         model->decref();
     41        if (model != NULL)
     42                model->decref();
    4043}
    4144
    42 void ModelGeometry::p_formodel(ExtValue *args,ExtValue *ret)
     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()
    4349{
    44 Model *m=ModelObj::fromObject(*args);
    45 if (m!=NULL)
    46         {
    47         ModelGeometry *mg=new ModelGeometry((ModelObj*)m);
    48         mg->density=density;
    49         ret->setObject(ModelGeometry::makeDynamicObject(mg));
    50         }
    51 else
    52         ret->setEmpty();
     50        cached_volume = -1;
     51        cached_area = -1;
     52        cached_sizes.x = -1;
    5353}
    5454
    55 void ModelGeometry::p_volume(ExtValue *args,ExtValue *ret)
     55// Invalidates cached results if a new density is requested
     56// (called in all geometry calculation functions)
     57void ModelGeometry::onDensityChanged()
    5658{
    57 ret->setDouble(ModelGeometryInfo::volume(*model,density));
     59        if (cached_for_density != density)
     60        {
     61                invalidateAllCached();
     62                cached_for_density = density;
     63        }
    5864}
    5965
    60 void ModelGeometry::p_area(ExtValue *args,ExtValue *ret)
     66void ModelGeometry::p_formodel(ExtValue *args, ExtValue *ret)
    6167{
    62 ret->setDouble(ModelGeometryInfo::area(*model,density));
     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();
    6377}
    6478
    65 void ModelGeometry::p_sizesandaxes(ExtValue *args,ExtValue *ret)
     79void ModelGeometry::p_volume(ExtValue *args, ExtValue *ret)
    6680{
    67 Pt3D sizes; Orient axes;
    68 ModelGeometryInfo::findSizesAndAxesOfModel(*model,density,sizes,axes);
    69 VectorObject* n=new VectorObject;
    70 n->data+=new ExtValue(Pt3D_Ext::makeDynamicObject(sizes));
    71 n->data+=new ExtValue(Orient_Ext::makeDynamicObject(new Orient_Ext(axes)));
    72 ret->setObject(n->makeObject());
     81        onDensityChanged();
     82        if (cached_volume < 0) //calculate if invalid
     83                cached_volume = ModelGeometryInfo::volume(*model, density);
     84        ret->setDouble(cached_volume);
    7385}
     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}
  • cpp/frams/model/geometry/modelgeoclass.h

    r235 r242  
    44#include <frams/model/modelobj.h>
    55
    6 class ModelGeometry: public DestrBase
     6class ModelGeometry : public DestrBase
    77{
    8   public:
    9 ModelObj *model;
    10 double density;
    11 Param par;
     8public:
     9        ModelObj *model;
     10        double density;
    1211
    13 ModelGeometry(ModelObj *mo=NULL);
    14 ~ModelGeometry();
     12        //"cached" fields let avoid redundant computations when asking for the same properties of the same model at the same density
     13        double cached_for_density;
     14        double cached_volume, cached_area;
     15        Pt3D cached_sizes; Orient cached_axes;
     16
     17        Param par;
     18
     19        ModelGeometry(ModelObj *mo = NULL);
     20        ~ModelGeometry();
     21
     22        void invalidateAllCached();
     23        void onDensityChanged();
    1524
    1625#define STATRICKCLASS ModelGeometry
    17 PARAMPROCDEF(p_formodel);
    18 PARAMPROCDEF(p_volume);
    19 PARAMPROCDEF(p_area);
    20 PARAMPROCDEF(p_sizesandaxes);
     26        PARAMPROCDEF(p_formodel);
     27        PARAMPROCDEF(p_volume);
     28        PARAMPROCDEF(p_area);
     29        PARAMPROCDEF(p_sizesandaxes);
    2130#undef STATRICKCLASS
    2231
    23 static ExtObject makeDynamicObject(ModelGeometry* mg);
     32        static ExtObject makeDynamicObject(ModelGeometry* mg);
    2433};
    2534
Note: See TracChangeset for help on using the changeset viewer.