1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
#pragma once
//#######################################################################################
//# #
//# CLOUDCOMPARE PLUGIN: qCSF #
//# #
//# This program 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; version 2 or later of the License. #
//# #
//# This program 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. #
//# #
//# Please cite the following paper, If you use this plugin in your work. #
//# #
//# Zhang W, Qi J, Wan P, Wang H, Xie D, Wang X, Yan G. An Easy-to-Use Airborne LiDAR #
//# Data Filtering Method Based on Cloth Simulation. Remote Sensing. 2016; 8(6):501. #
//# #
//# Copyright #
//# RAMM laboratory, School of Geography, Beijing Normal University #
//# (http://ramm.bnu.edu.cn/) #
//# #
//# Wuming Zhang; Jianbo Qi; Peng Wan; Hongtao Wang #
//# #
//# contact us: 2009zwm@gmail.com; wpqjbzwm@126.com #
//# #
//#######################################################################################
//This source code is about a ground filtering algorithm for airborn LiDAR data
//based on physical process simulations, specifically cloth simulation.
//
//This code is based on a Cloth Simulation Tutorial at the cg.alexandra.dk blog.
//Thanks to Jesper Mosegaard (clothTutorial@jespermosegaard.dk)
//
//When applying the cloth simulation to LIDAR point filtering. A lot of features
//have been added to the original source code, including
//* configuration file management
//* point cloud data read/write
//* point-to-point collsion detection
//* nearest point search structure from CGAL
//* addding a terrain class
//using discrete steps (drop and pull) to approximate the physical process
//Finding the max height value in nearest N points aroud every particles, as the lowest position where the particles can get.ÿϵΧڽN㣬Ըֵ߳Ϊܵ͵㡣
//local
#include "Vec3.h"
#include "Particle.h"
//system
#include <vector>
class ccMesh;
class Cloth
{
private:
// total number of particles is num_particles_width*num_particles_height
int constraint_iterations;
//double time_step;
std::vector<Particle> particles; // all particles that are part of this cloth
// std::vector<Constraint> constraints; // alle constraints between particles as part of this cloth
//parameters of slope postpocessing
double smoothThreshold;
double heightThreshold;
//heightvalues
std::vector<double> heightvals;
//movable particle index
std::vector<int> movableIndex;
std::vector< std::vector<int> > particle_edges;
//record
inline void addConstraint(Particle *p1, Particle *p2)
{ /*constraints.push_back(Constraint(p1, p2));*/
p1->neighborsList.push_back(p2); //record the neighbor for each particle
p2->neighborsList.push_back(p1);
}
public:
inline Particle& getParticle(int x, int y) { return particles[y*num_particles_width + x]; }
inline const Particle& getParticle(int x, int y) const { return particles[y*num_particles_width + x]; }
inline Particle& getParticleByIndex(int index) { return particles[index]; }
inline const Particle& getParticleByIndex(int index) const { return particles[index]; }
int num_particles_width; // number of particles in "width" direction
int num_particles_height; // number of particles in "height" direction
Vec3 origin_pos;
double step_x, step_y;
inline int getSize() const { return num_particles_width * num_particles_height; }
inline std::vector<double>& getHeightvals() { return heightvals; }
public:
/* This is a important constructor for the entire system of particles and constraints */
Cloth( const Vec3& origin_pos,
int num_particles_width,
int num_particles_height,
double step_x,
double step_y,
double smoothThreshold,
double heightThreshold,
int rigidness/*,
double time_step*/);
void setheightvals(const std::vector<double>& heightvals)
{
this->heightvals = heightvals;
}
/** This is an important method where the time is progressed one time step for the entire cloth.
This includes calling satisfyConstraint() for every constraint, and calling timeStep() for all particles
**/
double timeStep();
/* used to add gravity to all particles */
void addForce(double f);
//detecting collision of cloth and terrain
void terrainCollision();
//implementing postpocessing to movable particles
void movableFilter();
struct XY
{
XY(int x1, int y1)
: x(x1)
, y(y1)
{}
int x;
int y;
};
void findUnmovablePoint(const std::vector<XY>& connected,
const std::vector<double>& heightvals,
std::vector<int>& edgePoints);
void handle_slop_connected( const std::vector<int>& edgePoints,
const std::vector<XY>& connected,
const std::vector< std::vector<int> >& neighbors,
const std::vector<double> &heightvals);
//! Converts the cloth to a CC mesh structure
ccMesh* toMesh() const;
};
|