Files
secondo/Algebras/Pointcloud2/utilityOperators/opCreatePc2Shapes.cpp
2026-01-23 17:03:45 +08:00

201 lines
7.3 KiB
C++

/*
----
This file is part of SECONDO.
Copyright (C) 2019,
Faculty of Mathematics and Computer Science,
Database Systems for New Applications.
SECONDO is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
SECONDO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
//[<] [\ensuremath{<}]
//[>] [\ensuremath{>}]
\setcounter{tocdepth}{3}
\tableofcontents
0 Pointcloud2 createPc2Shapes operator
Creates a Pointcloud2 with planes, spheres, cylinders and cones.
Parameters are:
createPc2Shapes(planeCount, sphereCount, cylinderCount, coneCount,
pointDist, shapeSizeMin, shapeSizeMax, spaceSize,
diffusion, noisePointCount, rndSeed)
* planeCount etc. is the number of planes etc. to be created by the
operator
* pointDist is the regular distance between two points (e.g. 0.1),
* shapeSizeMin/Max is the extent of the shape in any dimension
(e.g. setting Min = 5.0 and Max = 8.0 could create a plane of size
5.5 x 7.4 with 55 * 74 points if pointDist is 0.1)
* spaceSize is the extent of the Pointcloud2 bbox in every dimension.
The shapes will be created at random locations within that space
(e.g. spaceSize = 30.0 for a bbox [0.0 - 30.0, 0.0 - 30.0, 0.0 - 30.0])
* diffusion will be added to every point in any dimension (e.g. 0.02 to add
random numbers in [-0.02, 0.02]
* noisePointCount is the total number of random points added as noise
anywhere in the given space
* rndSeed is the seed for the random number generator. With rndSeed = 0,
the current system time is used as a seed; with positive values, the
given value itself is used to generate reproducible results.
Example: createPc2Shapes(2, 2, 2, 2, 0.1, 2.0, 3.0, 20.0, 0.01, 50, 1); will
create 2 planes, 2 spheres, 2 cylinders, and 2 cones, each of size 2.0 - 3.0
in any dimension at (reproducible) random locations in the space
[0.0 - 20.0, 0.0 - 20.0, 0.0 - 20.0], diffuse each point by a random number
in [-0.01, 0.01], and then add 50 points of noise at random positions within
that space. Since rndSeed is positive, the exact same objects will be created
if the function is called again with the same parameters.
*/
#include "opCreatePc2Shapes.h"
#include <cmath>
#include <math.h>
#include <iostream>
#include <algorithm>
using namespace std;
using namespace pointcloud2;
extern NestedList *nl;
ListExpr op_createPc2Shapes::createPc2ShapesTM(ListExpr args) {
const string err("createPc2Shapes(int planeCount, int sphereCount, "
"int cylinderCount, int coneCount, real pointDist, "
"real shapeSizeMin, real shapeSizeMax, real spaceSize, "
"real diffusion, int noisePointCount, int rndSeed) expected");
const int expectedArgsLength = 11;
int argsLength = nl->ListLength(args);
if (argsLength != expectedArgsLength) {
stringstream st;
st << "wrong number of arguments: got " << argsLength
<< " but expected " << expectedArgsLength << ": " << err;
return listutils::typeError(st.str());
}
ListExpr rest = args;
stringstream wrongArgTypes;
wrongArgTypes << "wrong argument type in argument ";
size_t wrongCount = 0;
for (int i = 1; i <= expectedArgsLength; ++i) {
ListExpr arg = nl->First(rest);
bool expectedInt = (i <= 4 || i >= 10);
bool expectedReal = !expectedInt;
if ( (expectedInt && !CcInt::checkType(arg))
|| (expectedReal && !CcReal::checkType(arg))) {
if (wrongCount > 0)
wrongArgTypes << ", ";
++wrongCount;
wrongArgTypes << i;
if (expectedInt)
wrongArgTypes << " (int expected)";
else if (expectedReal)
wrongArgTypes << " (real expected)";
}
rest = nl->Rest(rest);
}
if (wrongCount > 0) {
wrongArgTypes << ": " << err;
return listutils::typeError(wrongArgTypes.str());
}
ListExpr result = Pointcloud2::cloudTypeWithParams(
nl->SymbolAtom(
Referencesystem::toString(Referencesystem::Type::EUCLID)));
return result;
}
int op_createPc2Shapes::createPc2ShapesVM(Word* args, Word& result,
int message, Word& local, Supplier s) {
// DEBUG
// const size_t max_memory = qp->GetMemorySize(s); // test machine: 512 MB
// cout << "Memory Size for Operator: " << max_memory << " MB" << endl;
// get args
int planeCount = (static_cast<CcInt*>(args[0].addr))->GetIntval();
int sphereCount = (static_cast<CcInt*>(args[1].addr))->GetIntval();
int cylinderCount = (static_cast<CcInt*>(args[2].addr))->GetIntval();
int coneCount = (static_cast<CcInt*>(args[3].addr))->GetIntval();
double pointDist = (static_cast<CcReal*>(args[4].addr))->GetRealval();
double shapeSizeMin = (static_cast<CcReal*>(args[5].addr))->GetRealval();
double shapeSizeMax = (static_cast<CcReal*>(args[6].addr))->GetRealval();
double spaceSize = (static_cast<CcReal*>(args[7].addr))->GetRealval();
double diffusion = (static_cast<CcReal*>(args[8].addr))->GetRealval();
int noisePointCount = (static_cast<CcInt*>(args[9].addr))->GetIntval();
int rndSeed = (static_cast<CcInt*>(args[10].addr))->GetIntval();
// ensure values are positive or 0
planeCount = MAX(planeCount , 0);
sphereCount = MAX(sphereCount, 0);
cylinderCount = MAX(cylinderCount, 0);
coneCount = MAX(coneCount, 0);
pointDist = std::abs(pointDist);
shapeSizeMin = std::abs(shapeSizeMin);
shapeSizeMax = std::abs(shapeSizeMax);
shapeSizeMax = MAX(shapeSizeMin, shapeSizeMax);
spaceSize = std::abs(spaceSize);
diffusion = std::abs(diffusion);
noisePointCount = MAX(noisePointCount, 0);
rndSeed = (rndSeed < 0) ? -rndSeed : rndSeed;
// get result Pointcloud2
result = qp->ResultStorage(s);
Pointcloud2* pc2 = static_cast<Pointcloud2*>(result.addr);
ShapeGenerator gen { pc2,
unsigned(planeCount), unsigned(sphereCount),
unsigned(cylinderCount), unsigned(coneCount),
pointDist, shapeSizeMin, shapeSizeMax, spaceSize,
diffusion, unsigned(noisePointCount), unsigned(rndSeed) };
gen.generate();
return 0;
}
std::string op_createPc2Shapes::getOperatorSpec(){
return OperatorSpec(
" int^4 x real^5 x int -> pointcloud2",
" createPc2Shapes(_, _, _, _, _, _, _, _, _, _) ",
" Creates a Pointcloud2 with planes, spheres etc. ",
" query createPc2Shapes(1, 1, 1, 1, 0.3, 5.0, 8.0, 30.0, 0.02, 50, 0)"
).getStr();
}
std::shared_ptr<Operator> op_createPc2Shapes::getOperator(){
return std::make_shared<Operator>("createPc2Shapes",
getOperatorSpec(),
&op_createPc2Shapes::createPc2ShapesVM,
Operator::SimpleSelect,
&op_createPc2Shapes::createPc2ShapesTM);
}