source: cpp/frams/_demos/geometry/geometrytestutils.cpp @ 999

Last change on this file since 999 was 999, checked in by Maciej Komosinski, 9 months ago

More consistent usage of "shapetype" (vs. "shape")

  • Property svn:eol-style set to native
File size: 8.4 KB
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
[972]2// Copyright (C) 1999-2020  Maciej Komosinski and Szymon Ulatowski.
[286]3// See LICENSE.txt for details.
[191]4
5#include "geometrytestutils.h"
6
7#include "../genotypeloader.h"
[547]8#include "frams/genetics/preconfigured.h"
[382]9#include <common/virtfile/stdiofile.h>
[550]10#include <common/loggers/loggertostdout.h>
[191]11#include <math.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <time.h>
15
16int printGenotypesList(const char *file)
17{
18        long count = 0;
19        long totalSize = 0;
[732]20        GenotypeMiniLoader loader(file);
21        GenotypeMini *genotype;
22
[191]23        while (genotype = loader.loadNextGenotype())
24        {
25                count++;
[972]26                totalSize += genotype->genotype.length();
[732]27
[972]28                fprintf(stderr, "%d. (%6d chars) %s\n", count, genotype->genotype.length(),
[348]29                        genotype->name.c_str());
[191]30        }
[732]31
32        if (loader.getStatus() == GenotypeMiniLoader::OnError)
[191]33        {
[348]34                fprintf(stderr, "Error: %s\n", loader.getError().c_str());
[191]35                return 2;
36        }
37        else
38        {
39                fprintf(stderr, "\ntotal: %d items, %d chars\n", count, totalSize);
40                return 0;
41        }
42}
43
44class TestInvoker
45{
[732]46public:
47        virtual void operator()(Model &model) = 0;
[737]48        virtual ~TestInvoker() {}
[191]49};
50
51int executeTestUsingLoadedModel(const char *file, const char *genoId, TestInvoker &test)
52{
53        const char* genoName = genoId;
54        const int genoIndex = isdigit(genoId[0]) ? atol(genoId) : 0;
55        long count = 0;
[732]56        GenotypeMiniLoader loader(file);
57        GenotypeMini *genotype;
58
[191]59        while (genotype = loader.loadNextGenotype())
60        {
61                count++;
[732]62
[348]63                if ((genoIndex == count) || (strcmp(genotype->name.c_str(), genoName) == 0))
[191]64                {
[999]65                        Model model(genotype->genotype, Model::SHAPETYPE_UNKNOWN);
[732]66
[191]67                        if (!model.isValid())
68                        {
[662]69                                fprintf(stderr, "Cannot build a valid Model from this genotype!\n");
[191]70                                return 4;
71                        }
[662]72                        SolidsShapeTypeModel sst_model(model);
73                        test(sst_model);
[191]74                        return 0;
75                }
76        }
[732]77
78        if (loader.getStatus() == GenotypeMiniLoader::OnError)
[191]79        {
[348]80                fprintf(stderr, "Error: %s\n", loader.getError().c_str());
[191]81                return 2;
82        }
83        else
84        {
85                fprintf(stderr, "Genotype %s not found in %s\n", genoId, file);
86                return 3;
87        }
88}
89
90int executeTestUsingRandomModel(int shape, TestInvoker &test)
91{
92        Model model;
93        model.open();
94
95        if ((shape < 1) || (shape > 3))
96        {
[732]97                shape = (rand() % 3) + 1;
[191]98        }
99
100        Part *part = model.addNewPart(Part::Shape(shape));
101        GeometryTestUtils::randomizePositionScaleAndOrient(part);
102
103        model.close();
104        test(model);
105        GeometryTestUtils::describePart(part, stdout);
[318]106        return 0;
[191]107}
108
[732]109class ModelBasedTestInvoker : public TestInvoker
[191]110{
[732]111private:
112        void(*test)(Model &);
113public:
114        ModelBasedTestInvoker(void(*_test)(Model &)) :
115                test(_test)
116        {}
117        void operator()(Model &model)
118        {
119                test(model);
120        }
[191]121};
122
[732]123int GeometryTestUtils::execute(const SString header, int argc, char *argv[], void(*test)(Model &))
[191]124{
[550]125        LoggerToStdout messages_to_stdout(LoggerBase::Enable); //comment this object out to mute error/warning messages
[299]126        StdioFileSystem_autoselect stdiofilesys;
[550]127        PreconfiguredGenetics genetics;
[732]128
[550]129        srand(time(NULL));
130
[191]131        if ((argc == 3) && (strcmp("-l", argv[1]) == 0))
132        {
133                return printGenotypesList(argv[2]);
134        }
[732]135
[191]136        if ((argc == 4) && (strcmp("-l", argv[1]) == 0))
137        {
138                ModelBasedTestInvoker invoker(test);
139                return executeTestUsingLoadedModel(argv[2], argv[3], invoker);
140        }
[732]141
[191]142        if ((argc == 2) && (strcmp("-c", argv[1]) == 0))
143        {
144                ModelBasedTestInvoker invoker(test);
145                return executeTestUsingRandomModel(-1, invoker);
146        }
[732]147
[191]148        if ((argc == 3) && (strcmp("-c", argv[1]) == 0) && isdigit(argv[2][0]))
149        {
150                int shape = atol(argv[2]);
151                ModelBasedTestInvoker invoker(test);
152                return executeTestUsingRandomModel(shape, invoker);
153        }
[732]154
[191]155        fprintf(stderr,
156                "%s\n\n"
157                "argument lists:\n"
158                "-l FILENAME            - to print list of models in file\n"
159                "-l FILENAME GENO_ID    - to load model from file and run test\n"
160                "-c [SHAPE]             - to create simple random model and run test\n\n"
161                "FILENAME - name of file containing named f0 genotypes\n"
162                "GENO_ID - either genotype name or index (1-based)\n"
163                "SHAPE - 1=ellipsoid, 2=cuboid, 3=cylinder, others or none=random\n",
[348]164                header.c_str());
[191]165        return 1;
166}
167
[732]168class ModelAndDensityBasedTestInvoker : public TestInvoker
[191]169{
[732]170private:
171        void(*test)(Model &, const double);
172        double density;
173public:
174        ModelAndDensityBasedTestInvoker(void(*_test)(Model &, const double), double _density) :
175                test(_test),
176                density(_density)
177        {}
178
179        void operator()(Model &model)
180        {
181                test(model, density);
182        }
[191]183};
184
185int GeometryTestUtils::execute(const SString header, int argc, char *argv[],
[732]186        void(*test)(Model &, const double))
[191]187{
[550]188        LoggerToStdout messages_to_stdout(LoggerBase::Enable); //comment this object out to mute error/warning messages
[299]189        StdioFileSystem_autoselect stdiofilesys;
[550]190        PreconfiguredGenetics genetics;
[732]191
[550]192        srand(time(NULL));
193
[191]194        if ((argc == 3) && (strcmp("-l", argv[1]) == 0))
195        {
196                return printGenotypesList(argv[2]);
197        }
198
199        if ((argc == 5) && (strcmp("-l", argv[1]) == 0) && isdigit(argv[4][0]))
200        {
201                double density = atol(argv[4]);
202                ModelAndDensityBasedTestInvoker invoker(test, density);
203                return executeTestUsingLoadedModel(argv[2], argv[3], invoker);
204        }
[732]205
[191]206        if ((argc == 3) && (strcmp("-c", argv[1]) == 0) && isdigit(argv[2][0]))
207        {
208                double density = atol(argv[2]);
209                ModelAndDensityBasedTestInvoker invoker(test, density);
210                return executeTestUsingRandomModel(-1, invoker);
211        }
[732]212
[191]213        if ((argc == 4) && (strcmp("-c", argv[1]) == 0) && isdigit(argv[2][0]) && isdigit(argv[3][0]))
214        {
215                double density = atol(argv[2]);
216                int shape = atol(argv[3]);
217                ModelAndDensityBasedTestInvoker invoker(test, density);
218                return executeTestUsingRandomModel(shape, invoker);
219        }
[732]220
[191]221        fprintf(stderr,
222                "%s\n\n"
[662]223                "argument list:\n"
224                "-l FILENAME                    - to print the list of models in file\n"
225                "-l FILENAME GENO_ID DENSITY    - to load the model from the file and run test\n"
226                "-c DENSITY [SHAPE]             - to create a simple random model and run test\n\n"
227                "FILENAME - name of the file containing named f0 genotypes\n"
[191]228                "GENO_ID - either genotype name or index (1-based)\n"
229                "DENSITY - minimal number of samples per unit\n"
[299]230                "SHAPE - 1=ellipsoid, 2=cuboid, 3=cylinder, others or none=random\n",
[348]231                header.c_str());
[191]232        return 1;
233}
234
235void GeometryTestUtils::addAnchorToModel(Model &model)
236{
237        Part *part = model.addNewPart(Part::SHAPE_ELLIPSOID);
[732]238
[191]239        part->p = Pt3D(0);
240        part->scale = Pt3D(0.1);
241        part->vcolor = Pt3D(1.0, 0.0, 1.0);
[732]242
[191]243        addAxesToModel(Pt3D(0.5), Orient(Orient_1), Pt3D(0.0), model);
244}
245
246void GeometryTestUtils::addPointToModel(const Pt3D &markerLocation, Model &model)
247{
248        Part *anchor = model.getPart(0);
249        Part *part = model.addNewPart(Part::SHAPE_ELLIPSOID);
[732]250
[191]251        part->p = Pt3D(markerLocation);
252        part->scale = Pt3D(0.05);
253        part->vcolor = Pt3D(1.0, 1.0, 0.0);
[732]254
[544]255        model.addNewJoint(anchor, part, Joint::SHAPE_FIXED);
[191]256}
257
258void GeometryTestUtils::addAxesToModel(const Pt3D &sizes, const Orient &axes, const Pt3D &center,
259        Model &model)
260{
261        Part *anchor = model.getPart(0);
262        Part *part;
[732]263
[191]264        part = model.addNewPart(Part::SHAPE_CUBOID);
265        part->scale = Pt3D(sizes.x, 0.05, 0.05);
266        part->setOrient(axes);
267        part->p = center;
268        part->vcolor = Pt3D(1.0, 0.0, 0.0);
[544]269        model.addNewJoint(anchor, part, Joint::SHAPE_FIXED);
[732]270
[191]271        part = model.addNewPart(Part::SHAPE_CUBOID);
272        part->scale = Pt3D(0.05, sizes.y, 0.05);
273        part->setOrient(axes);
274        part->p = center;
275        part->vcolor = Pt3D(0.0, 1.0, 0.0);
[544]276        model.addNewJoint(anchor, part, Joint::SHAPE_FIXED);
[732]277
[191]278        part = model.addNewPart(Part::SHAPE_CUBOID);
279        part->scale = Pt3D(0.05, 0.05, sizes.z);
280        part->setOrient(axes);
281        part->p = center;
282        part->vcolor = Pt3D(0.0, 0.0, 1.0);
[544]283        model.addNewJoint(anchor, part, Joint::SHAPE_FIXED);
[191]284}
285
286void GeometryTestUtils::mergeModels(Model &target, Model &source)
287{
288        Part *targetAnchor = target.getPart(0);
289        Part *sourceAnchor = source.getPart(0);
[732]290
[191]291        target.moveElementsFrom(source);
[732]292
[544]293        target.addNewJoint(targetAnchor, sourceAnchor, Joint::SHAPE_FIXED);
[191]294}
295
296double frand(double from, double width)
297{
[732]298        return from + width * ((rand() % 10000) / 10000.0);
[191]299}
300
301void GeometryTestUtils::randomizePositionScaleAndOrient(Part *part)
302{
303        part->p = Pt3D(frand(1.5, 1.0), frand(1.5, 1.0), frand(1.5, 1.0));
304        part->scale = Pt3D(frand(0.1, 0.9), frand(0.1, 0.9), frand(0.1, 0.9));
305        part->setRot(Pt3D(frand(0.0, M_PI), frand(0.0, M_PI), frand(0.0, M_PI)));
306}
307
308void GeometryTestUtils::describePart(const Part *part, FILE *output)
309{
310        fprintf(output, "# shape=%d\n", part->shape);
311        fprintf(output, "# x=%f\n", part->p.x);
312        fprintf(output, "# y=%f\n", part->p.y);
313        fprintf(output, "# z=%f\n", part->p.z);
314        fprintf(output, "# sx=%f\n", part->scale.x);
315        fprintf(output, "# sy=%f\n", part->scale.y);
316        fprintf(output, "# sz=%f\n", part->scale.z);
317        fprintf(output, "# rx=%f\n", part->rot.x);
318        fprintf(output, "# ry=%f\n", part->rot.y);
319        fprintf(output, "# rz=%f\n", part->rot.z);
320}
Note: See TracBrowser for help on using the repository browser.