mirror of https://github.com/CGAL/cgal
Changes to guarantee there will be no border case problems with cone angle in [0, PI].
This commit is contained in:
parent
68197c0352
commit
65fc0a0b6b
|
|
@ -58,32 +58,21 @@ public:
|
||||||
/**
|
/**
|
||||||
* Samples points from unit-disk.
|
* Samples points from unit-disk.
|
||||||
* @param number_of_points number of points to be picked
|
* @param number_of_points number of points to be picked
|
||||||
* @param cone_angle opening angle of cone (might be necessary for weighting)
|
|
||||||
* @param[out] out_it sampled points from disk, each point is tuple of:
|
* @param[out] out_it sampled points from disk, each point is tuple of:
|
||||||
* - coordinate-x
|
* - coordinate-x
|
||||||
* - coordinate-y
|
* - coordinate-y
|
||||||
* - weight (proportional to angle between cone-normal)
|
* - weight (proportional to distance from disk center)
|
||||||
*/
|
*/
|
||||||
template<class OutputIterator>
|
template<class OutputIterator>
|
||||||
void operator()(int number_of_points,
|
void operator()(int number_of_points,
|
||||||
double cone_angle,
|
|
||||||
OutputIterator out_it) const {
|
OutputIterator out_it) const {
|
||||||
if(cone_angle <= 0.0) {
|
|
||||||
CGAL_warning(false
|
|
||||||
&& "Warning: cone angle smaller than or equal to zero will be assigned to epsilon!");
|
|
||||||
cone_angle = (std::numeric_limits<double>::epsilon)();
|
|
||||||
}
|
|
||||||
|
|
||||||
const double golden_ratio = 3.0 - std::sqrt(5.0);
|
const double golden_ratio = 3.0 - std::sqrt(5.0);
|
||||||
|
|
||||||
if(uniform) {
|
if(uniform) {
|
||||||
const double length_of_normal = 1.0 / tan(cone_angle / 2.0);
|
|
||||||
const double angle_st_dev = cone_angle / CGAL_ANGLE_ST_DEV_DIVIDER;
|
|
||||||
for(int i = 0; i < number_of_points; ++i) {
|
for(int i = 0; i < number_of_points; ++i) {
|
||||||
double Q = i * golden_ratio * CGAL_PI;
|
double Q = i * golden_ratio * CGAL_PI;
|
||||||
double R = std::sqrt(static_cast<double>(i) / number_of_points);
|
double R = std::sqrt(static_cast<double>(i) / number_of_points);
|
||||||
double angle = atan(R / length_of_normal);
|
double weight = exp(-0.5 * (std::pow(R / CGAL_ANGLE_ST_DEV_DIVIDER, 2)));
|
||||||
double weight = exp(-0.5 * (std::pow(angle / angle_st_dev, 2)));
|
|
||||||
*out_it++ = Tuple(R * cos(Q), R * sin(Q), weight);
|
*out_it++ = Tuple(R * cos(Q), R * sin(Q), weight);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -137,29 +126,19 @@ public:
|
||||||
/**
|
/**
|
||||||
* Samples points from unit-disk.
|
* Samples points from unit-disk.
|
||||||
* @param number_of_points number of points to be picked
|
* @param number_of_points number of points to be picked
|
||||||
* @param cone_angle opening angle of cone (might be necessary for weighting)
|
|
||||||
* @param[out] out_it sampled points from disk, each point is tuple of:
|
* @param[out] out_it sampled points from disk, each point is tuple of:
|
||||||
* - coordinate-x
|
* - coordinate-x
|
||||||
* - coordinate-y
|
* - coordinate-y
|
||||||
* - weight (proportional to angle between cone-normal)
|
* - weight (proportional to distance from disk center)
|
||||||
*
|
*
|
||||||
* Note: returned samples size = \f$ \lfloor \sqrt {number\_of\_points} \rfloor ^ 2 \f$
|
* Note: returned samples size = \f$ \lfloor \sqrt {number\_of\_points} \rfloor ^ 2 \f$
|
||||||
*/
|
*/
|
||||||
template<class OutputIterator>
|
template<class OutputIterator>
|
||||||
void operator()(int number_of_points,
|
void operator()(int number_of_points,
|
||||||
double cone_angle,
|
|
||||||
OutputIterator out_it) const {
|
OutputIterator out_it) const {
|
||||||
if(cone_angle <= 0.0) {
|
|
||||||
CGAL_warning(false
|
|
||||||
&& "Warning: cone angle smaller than or equal to zero will be assigned to epsilon!");
|
|
||||||
cone_angle = (std::numeric_limits<double>::epsilon)();
|
|
||||||
}
|
|
||||||
|
|
||||||
const int number_of_points_sqrt = static_cast<int>(std::sqrt(
|
const int number_of_points_sqrt = static_cast<int>(std::sqrt(
|
||||||
static_cast<double>(number_of_points)));
|
static_cast<double>(number_of_points)));
|
||||||
const double length_of_normal = 1.0 / tan(cone_angle / 2.0);
|
|
||||||
// use cone_angle / 3 as one standard deviation while weighting.
|
// use cone_angle / 3 as one standard deviation while weighting.
|
||||||
const double angle_st_dev = cone_angle / CGAL_ANGLE_ST_DEV_DIVIDER;
|
|
||||||
|
|
||||||
for(int i = 1; i <= number_of_points_sqrt; ++i)
|
for(int i = 1; i <= number_of_points_sqrt; ++i)
|
||||||
for(int j = 1; j <= number_of_points_sqrt; ++j) {
|
for(int j = 1; j <= number_of_points_sqrt; ++j) {
|
||||||
|
|
@ -167,8 +146,8 @@ public:
|
||||||
double w2 = static_cast<double>(j) / number_of_points_sqrt;
|
double w2 = static_cast<double>(j) / number_of_points_sqrt;
|
||||||
double R = w1;
|
double R = w1;
|
||||||
double Q = 2 * w2 * CGAL_PI;
|
double Q = 2 * w2 * CGAL_PI;
|
||||||
double angle = atan(R / length_of_normal);
|
|
||||||
double weight = exp(-0.5 * (pow(angle / angle_st_dev, 2)));
|
double weight = exp(-0.5 * (pow(R / CGAL_ANGLE_ST_DEV_DIVIDER, 2)));
|
||||||
*out_it++ = Tuple(R * cos(Q), R * sin(Q), weight);
|
*out_it++ = Tuple(R * cos(Q), R * sin(Q), weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -219,21 +198,11 @@ public:
|
||||||
*/
|
*/
|
||||||
template<class OutputIterator>
|
template<class OutputIterator>
|
||||||
void operator()(int number_of_points,
|
void operator()(int number_of_points,
|
||||||
double cone_angle,
|
|
||||||
OutputIterator out_it) const {
|
OutputIterator out_it) const {
|
||||||
if(cone_angle <= 0.0) {
|
|
||||||
CGAL_warning(false
|
|
||||||
&& "Warning: cone angle smaller than or equal to zero will be assigned to epsilon!");
|
|
||||||
cone_angle = (std::numeric_limits<double>::epsilon)();
|
|
||||||
}
|
|
||||||
|
|
||||||
const int number_of_points_sqrt = static_cast<int>(std::sqrt(
|
const int number_of_points_sqrt = static_cast<int>(std::sqrt(
|
||||||
static_cast<double>(number_of_points)));
|
static_cast<double>(number_of_points)));
|
||||||
const double length_of_normal = 1.0 / tan(cone_angle / 2.0);
|
|
||||||
const double fraction = (number_of_points_sqrt == 1) ? 0.0
|
const double fraction = (number_of_points_sqrt == 1) ? 0.0
|
||||||
: 2.0 / (number_of_points_sqrt -1);
|
: 2.0 / (number_of_points_sqrt -1);
|
||||||
// use cone_angle / 3 as one standard deviation while weighting.
|
|
||||||
const double angle_st_dev = cone_angle / CGAL_ANGLE_ST_DEV_DIVIDER;
|
|
||||||
|
|
||||||
for(int i = 0; i < number_of_points_sqrt; ++i)
|
for(int i = 0; i < number_of_points_sqrt; ++i)
|
||||||
for(int j = 0; j < number_of_points_sqrt; ++j) {
|
for(int j = 0; j < number_of_points_sqrt; ++j) {
|
||||||
|
|
@ -261,8 +230,8 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Q *= (CGAL_PI / 4.0);
|
Q *= (CGAL_PI / 4.0);
|
||||||
double angle = atan(R / length_of_normal);
|
|
||||||
double weight = exp(-0.5 * (pow(angle / angle_st_dev, 2)));
|
double weight = exp(-0.5 * (pow(R / CGAL_ANGLE_ST_DEV_DIVIDER, 2)));
|
||||||
*out_it++ = Tuple(R * cos(Q), R * sin(Q), weight);
|
*out_it++ = Tuple(R * cos(Q), R * sin(Q), weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ private:
|
||||||
typedef typename GeomTraits::Ray_3 Ray;
|
typedef typename GeomTraits::Ray_3 Ray;
|
||||||
typedef typename GeomTraits::Plane_3 Plane;
|
typedef typename GeomTraits::Plane_3 Plane;
|
||||||
typedef typename GeomTraits::Segment_3 Segment;
|
typedef typename GeomTraits::Segment_3 Segment;
|
||||||
|
typedef typename GeomTraits::FT FT;
|
||||||
|
|
||||||
typedef typename Polyhedron::Facet Facet;
|
typedef typename Polyhedron::Facet Facet;
|
||||||
|
|
||||||
|
|
@ -80,6 +81,7 @@ private:
|
||||||
|
|
||||||
typedef Vogel_disk_sampling<boost::tuple<double, double, double> >
|
typedef Vogel_disk_sampling<boost::tuple<double, double, double> >
|
||||||
Default_sampler;
|
Default_sampler;
|
||||||
|
|
||||||
// member variables
|
// member variables
|
||||||
private:
|
private:
|
||||||
GeomTraits traits;
|
GeomTraits traits;
|
||||||
|
|
@ -168,7 +170,7 @@ public:
|
||||||
FacetValueMap sdf_values,
|
FacetValueMap sdf_values,
|
||||||
DiskSampling disk_sampler) const {
|
DiskSampling disk_sampler) const {
|
||||||
Disk_samples_list disk_samples;
|
Disk_samples_list disk_samples;
|
||||||
disk_sampler(number_of_rays, cone_angle, std::back_inserter(disk_samples));
|
disk_sampler(number_of_rays, std::back_inserter(disk_samples));
|
||||||
|
|
||||||
for( ; facet_begin != facet_end; ++facet_begin) {
|
for( ; facet_begin != facet_end; ++facet_begin) {
|
||||||
boost::optional<double> sdf_value = calculate_sdf_value_of_facet(facet_begin,
|
boost::optional<double> sdf_value = calculate_sdf_value_of_facet(facet_begin,
|
||||||
|
|
@ -232,7 +234,7 @@ public:
|
||||||
bool accept_if_acute,
|
bool accept_if_acute,
|
||||||
DiskSampling disk_sampler) const {
|
DiskSampling disk_sampler) const {
|
||||||
Disk_samples_list disk_samples;
|
Disk_samples_list disk_samples;
|
||||||
disk_sampler(number_of_rays, cone_angle, std::back_inserter(disk_samples));
|
disk_sampler(number_of_rays, std::back_inserter(disk_samples));
|
||||||
|
|
||||||
return calculate_sdf_value_of_point(center, normal, skip, visitor, cone_angle,
|
return calculate_sdf_value_of_point(center, normal, skip, visitor, cone_angle,
|
||||||
accept_if_acute, disk_samples);
|
accept_if_acute, disk_samples);
|
||||||
|
|
@ -250,19 +252,23 @@ public:
|
||||||
double cone_angle,
|
double cone_angle,
|
||||||
bool accept_if_acute,
|
bool accept_if_acute,
|
||||||
const Disk_samples_list& disk_samples) const {
|
const Disk_samples_list& disk_samples) const {
|
||||||
|
if(cone_angle < 0.0 || cone_angle > CGAL_PI) {
|
||||||
|
CGAL_warning(false && "Cone angle is clamped between [0, CGAL_PI].");
|
||||||
|
cone_angle = (std::min)(CGAL_PI, (std::max)(0.0, cone_angle));
|
||||||
|
}
|
||||||
|
|
||||||
Plane plane(center, normal);
|
Plane plane(center, normal);
|
||||||
Vector v1 = plane.base1(), v2 = plane.base2();
|
Vector v1 = plane.base1(), v2 = plane.base2();
|
||||||
v1 = scale_functor(v1, static_cast<typename GeomTraits::FT>(1.0 / CGAL::sqrt(
|
v1 = scale_functor(v1, static_cast<FT>(1.0 / CGAL::sqrt(v1.squared_length())));
|
||||||
v1.squared_length())));
|
v2 = scale_functor(v2, static_cast<FT>(1.0 / CGAL::sqrt(v2.squared_length())));
|
||||||
v2 = scale_functor(v2, static_cast<typename GeomTraits::FT>(1.0 / CGAL::sqrt(
|
|
||||||
v2.squared_length())));
|
|
||||||
|
|
||||||
std::vector<std::pair<double, double> > ray_distances;
|
std::vector<std::pair<double, double> > ray_distances;
|
||||||
ray_distances.reserve(disk_samples.size());
|
ray_distances.reserve(disk_samples.size());
|
||||||
|
|
||||||
const typename GeomTraits::FT length_of_normal =
|
const FT normal_multiplier( cos(cone_angle / 2.0) );
|
||||||
static_cast<typename GeomTraits::FT>( 1.0 / tan(cone_angle / 2.0) );
|
const FT disk_multiplier ( sin(cone_angle / 2.0) );
|
||||||
Vector scaled_normal = scale_functor(normal, length_of_normal);
|
|
||||||
|
Vector scaled_normal = scale_functor(normal, normal_multiplier);
|
||||||
|
|
||||||
for(Disk_samples_list::const_iterator sample_it = disk_samples.begin();
|
for(Disk_samples_list::const_iterator sample_it = disk_samples.begin();
|
||||||
sample_it != disk_samples.end(); ++sample_it) {
|
sample_it != disk_samples.end(); ++sample_it) {
|
||||||
|
|
@ -271,11 +277,17 @@ public:
|
||||||
Primitive_id closest_id;
|
Primitive_id closest_id;
|
||||||
|
|
||||||
Vector disk_vector = sum_functor(
|
Vector disk_vector = sum_functor(
|
||||||
scale_functor(v1, static_cast<typename GeomTraits::FT>(sample_it->get<0>())),
|
scale_functor(v1, static_cast<FT>(disk_multiplier * sample_it->get<0>())),
|
||||||
scale_functor(v2, static_cast<typename GeomTraits::FT>(sample_it->get<1>())) );
|
scale_functor(v2, static_cast<FT>(disk_multiplier * sample_it->get<1>())) );
|
||||||
Vector ray_direction = sum_functor(scaled_normal, disk_vector);
|
Vector ray_direction = sum_functor(scaled_normal, disk_vector);
|
||||||
|
|
||||||
Ray ray(center, ray_direction);
|
Ray ray(center, ray_direction);
|
||||||
|
|
||||||
|
if(traits.is_degenerate_3_object()(ray)) {
|
||||||
|
CGAL_warning(false &&
|
||||||
|
"A degenerate ray is constructed. Most probable reason is using CGAL_PI as cone_angle parameter and also picking center of disk as a sample.");
|
||||||
|
}
|
||||||
|
|
||||||
boost::tie(is_intersected, intersection_is_acute, min_distance, closest_id)
|
boost::tie(is_intersected, intersection_is_acute, min_distance, closest_id)
|
||||||
= cast_and_return_minimum(ray, skip, accept_if_acute);
|
= cast_and_return_minimum(ray, skip, accept_if_acute);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue