NetDEM v1.0
Loading...
Searching...
No Matches
20_gen_dataset_ellipsoid_plane.cpp

This is an example of how to use the netdem library.

#include "igl_wrapper.hpp"
#include "particle.hpp"
#include "shape_plane.hpp"
#include "utils_math.hpp"
#include <fstream>
#include <iostream>
#include <random>
#include <sstream>
#include <string>
using namespace netdem;
using namespace std;
void SaveDatasetEllipsoidPlaneDetection(int num_samples, double (*ds_inputs)[4],
bool *ds_cnt_flags, string filename) {
stringbuf buf;
ostream os(&buf);
int os_width = 24;
os.setf(ios::scientific);
os.precision(15);
for (int i = 0; i < num_samples; i++) {
// write the data as one sample one row
for (int i_inputs = 0; i_inputs < 4; i_inputs++) {
os.width(os_width);
os << ds_inputs[i][i_inputs] << ", ";
}
os.width(3);
os << (ds_cnt_flags[i] ? 1 : 0) << endl;
}
ofstream outfile;
outfile.open(filename);
if (!outfile) {
cout << "cannot open file: " << filename << endl;
}
outfile << buf.str();
outfile.close();
cout << "data saved to: " << filename << endl;
}
void SaveDatasetEllipsoidPlaneResolution(int num_samples,
double (*ds_inputs)[4],
double (*ds_cnt_feats)[4],
string filename) {
stringbuf buf;
ostream os(&buf);
int os_width = 24;
os.setf(ios::scientific);
os.precision(15);
for (int i = 0; i < num_samples; i++) {
// skip the non-contact data
if (ds_cnt_feats[i][0] < 0)
continue;
// write the data as one sample one row
for (int i_inputs = 0; i_inputs < 4; i_inputs++) {
os.width(os_width);
os << ds_inputs[i][i_inputs] << ", ";
}
for (int i_outputs = 0; i_outputs < 3; i_outputs++) {
os.width(os_width);
os << ds_cnt_feats[i][i_outputs] << ", ";
}
os.width(os_width);
os << ds_cnt_feats[i][3] << endl;
}
ofstream outfile;
outfile.open(filename);
if (!outfile) {
cout << "cannot open file: " << filename << endl;
}
outfile << buf.str();
outfile.close();
cout << "data saved to: " << filename << endl;
}
void GenDatasetEllipsoidPlane(int num_samples = 100) {
// load particle
Ellipsoid ellipsoid = Ellipsoid(1, 1, 2);
ellipsoid.SetSize(1.0);
Particle obj_p = Particle(&ellipsoid);
cout << "particle created ... " << endl;
// load wall
Plane plane(0, 0, 0, 0, 0, 1);
Wall obj_w = Wall(&plane);
cout << "wall created ... " << endl;
// allocate memory
double(*ds_inputs)[4] = new double[num_samples][4];
bool *ds_cnt_flags = new bool[num_samples];
double(*ds_cnt_feats)[4] = new double[num_samples][4];
// random generator
UniformDistribution uniform_dist(0.0, 1.0);
// use spherical centroidal voronoi to sample uniform unit VecXT
VecXT<Vec3d> vertices = SphericalVoronoi::Solve(1000, 10000, 1.0e-4);
VecXT<Vec3i> facets;
IGLWrapper::ConvexHull(vertices, &vertices, &facets);
// random cases
for (int trial = 0, i = 0; trial < num_samples * 100; trial++) {
// random normal
int id_facet = floor(uniform_dist.Get() * facets.size());
auto vert_0 = vertices[facets[id_facet][0]];
auto vert_1 = vertices[facets[id_facet][1]];
auto vert_2 = vertices[facets[id_facet][2]];
double u_vert = uniform_dist.Get();
double v_vert = uniform_dist.Get() * (1 - u_vert);
double w_vert = 1 - u_vert - v_vert;
Vec3d dir_n = u_vert * vert_0 + v_vert * vert_1 + w_vert * vert_2;
Math::Normalize(&dir_n);
// random distance
Vec3d sup_pos, sup_dir{-dir_n[0], -dir_n[1], -dir_n[2]};
sup_pos = ellipsoid.SupportPoint(sup_dir);
double dist_sup = -Math::Dot(dir_n, sup_pos);
// use this to control the ratio of contact and non-contact cases
double cnt_prob = uniform_dist.Get();
double dist_min = cnt_prob > 0.6 ? dist_sup - 0.05 : dist_sup;
double dist_max = cnt_prob > 0.6 ? dist_sup : ellipsoid.GetBoundSphereRadius();
double dist_pc_to_plane =
dist_min + uniform_dist.Get() * (dist_max - dist_min);
double len_n = dist_sup - dist_pc_to_plane;
// transform the inputs to the wall position and rotation
// this is only for verification. No need to do this in contact solver
Vec3d dir_n_ref{0, 0, 1}, rot_axis;
rot_axis = Math::Cross(dir_n_ref, dir_n);
Vec4d quat;
quat[0] = 1 + Math::Dot(dir_n, dir_n_ref);
quat[1] = rot_axis[0];
quat[2] = rot_axis[1];
quat[3] = rot_axis[2];
Math::Quaternion::Normalize(&quat);
obj_w.SetPosition(-dist_pc_to_plane * dir_n[0],
-dist_pc_to_plane * dir_n[1],
-dist_pc_to_plane * dir_n[2]);
obj_w.SetQuaternion(quat[0], quat[1], quat[2], quat[3]);
if (len_n <= 0) {
// use distance from particle centroid to plane and plane normal as inputs
ds_inputs[i][0] = dist_pc_to_plane;
ds_inputs[i][1] = dir_n[0];
ds_inputs[i][2] = dir_n[1];
ds_inputs[i][3] = dir_n[2];
// contact status
ds_cnt_flags[i] = 0;
// volume and directional cross-section area of intersection as outputs
ds_cnt_feats[i][0] = -1;
ds_cnt_feats[i][1] = -1;
ds_cnt_feats[i][2] = -1;
ds_cnt_feats[i][3] = -1;
i++;
} else {
// use distance from particle centroid to plane and plane normal as inputs
ds_inputs[i][0] = dist_pc_to_plane;
ds_inputs[i][1] = dir_n[0];
ds_inputs[i][2] = dir_n[1];
ds_inputs[i][3] = dir_n[2];
// contact status
ds_cnt_flags[i] = 1;
// volume and directional cross-section area of intersection as outputs
ds_cnt_feats[i][0] = len_n;
ds_cnt_feats[i][1] = sup_pos[0] + 0.5 * len_n * dir_n[0];
ds_cnt_feats[i][2] = sup_pos[1] + 0.5 * len_n * dir_n[1];
ds_cnt_feats[i][3] = sup_pos[2] + 0.5 * len_n * dir_n[2];
// SolverGJKPW cnt_solver;
// LinearSpring cnt_model;
// cnt_solver.Init(&obj_p, &obj_w);
// auto cnt = ContactPW(&obj_p, &obj_w);
// cnt.SetCollisionModel(&cnt_model);
// cnt_solver.Detect();
// cnt_solver.ResolveInit(&cnt, 1.0e-4);
// auto &cnt_geoms = cnt.collision_entries[0].cnt_geoms;
// cout << cnt_geoms.len_n << ", " << cnt_geoms.pos[0] << ", "
// << cnt_geoms.pos[1] << ", " << cnt_geoms.pos[2] << endl;
// cout << ds_cnt_feats[i][0] << ", " << ds_cnt_feats[i][1] << ", "
// << ds_cnt_feats[i][2] << ", " << ds_cnt_feats[i][3] << endl;
i++;
}
if (((i + 1) % 100) == 0) {
cout << "number of samples: " << i + 1 << " ..." << endl;
}
if (i >= num_samples) {
break;
}
}
string root_dir = "local/examples/netdem/ann_models/ellipsoid_plane/";
SaveDatasetEllipsoidPlaneDetection(num_samples, ds_inputs, ds_cnt_flags,
root_dir + "dataset_detection.txt");
SaveDatasetEllipsoidPlaneResolution(num_samples, ds_inputs, ds_cnt_feats,
root_dir + "dataset_resolution.txt");
delete[] ds_inputs;
delete[] ds_cnt_flags;
delete[] ds_cnt_feats;
}
A class for representing an ellipsoid shape.
Definition shape_ellipsoid.hpp:15
void SetSize(double d) override
Set the size of the Ellipsoid object.
Definition shape_ellipsoid.cpp:51
Vec3d SupportPoint(Vec3d const &dir) override
Compute the support point in a given direction for the Ellipsoid object.
Definition shape_ellipsoid.cpp:168
Definition particle.hpp:26
A class for representing a plane with a center point and normal vector.
Definition shape_plane.hpp:22
virtual double GetBoundSphereRadius() const
Return the inertia of the shape.
Definition shape.cpp:126
Generates random numbers from a uniform distribution.
Definition distribution_uniform.hpp:15
A class representing a wall object in a physics simulation.
Definition wall.hpp:32
void SetQuaternion(double q_0, double q_1, double q_2, double q_3)
Sets the orientation of the wall using a quaternion.
Definition wall.cpp:61
void SetPosition(double pos_x, double pos_y, double pos_z)
Sets the position of the wall.
Definition wall.cpp:41
Definition bond_entry.hpp:7
std::vector< T > VecXT
Definition utils_macros.hpp:31
std::array< double, 3 > Vec3d
Definition utils_macros.hpp:18
len_n
Definition json_serilization.hpp:20
std::array< double, 4 > Vec4d
Definition utils_macros.hpp:19
dir_n
Definition json_serilization.hpp:19