Merge remote-tracking branch 'mine/Surface_mesh-PLY_IO-GF' into Surface_mesh-PLY_IO-GF

This commit is contained in:
Simon Giraudot 2019-04-09 15:11:58 +02:00
commit 717137e48f
67 changed files with 2735 additions and 2326 deletions

View File

@ -479,7 +479,7 @@ void xAlci_main_window::setup(int w, int h)
tab_widget->addTab(cad_tab,"cad"); tab_widget->addTab(cad_tab,"cad");
tab_widget->addTab(arr_tab,"arrangement"); tab_widget->addTab(arr_tab,"arrangement");
*widget << CGAL::LineWidth(2) << CGAL::BackgroundColor(CGAL::WHITE); *widget << CGAL::LineWidth(2) << CGAL::BackgroundColor(CGAL::white());
resize(w,h); resize(w,h);
double ratio = 1.0;//(double)h/w; double ratio = 1.0;//(double)h/w;
widget->set_window(-1, 1, -ratio, ratio, true); widget->set_window(-1, 1, -ratio, ratio, true);

View File

@ -277,11 +277,11 @@ inline std::ostream & operator<<(std::ostream & os, const Arr::Vertex & vertex)
inline Window_stream & operator<<(Window_stream & ws, Arr & arr) inline Window_stream & operator<<(Window_stream & ws, Arr & arr)
{ {
Arr::Edge_iterator ei; Arr::Edge_iterator ei;
ws << CGAL::BLUE; ws << CGAL::blue();
for (ei = arr.edges_begin(); ei != arr.edges_end(); ++ei) for (ei = arr.edges_begin(); ei != arr.edges_end(); ++ei)
ws << (*ei).curve(); ws << (*ei).curve();
Arr::Vertex_iterator vi; Arr::Vertex_iterator vi;
ws << CGAL::RED; ws << CGAL::red();
for (vi = arr.vertices_begin(); vi != arr.vertices_end(); ++vi) for (vi = arr.vertices_begin(); vi != arr.vertices_end(); ++vi)
ws << (*vi).point(); ws << (*vi).point();
return ws; return ws;
@ -474,7 +474,7 @@ public:
m_window->flush(); m_window->flush();
#else #else
m_window->lock(); m_window->lock();
*m_window << CGAL::BackgroundColor(CGAL::WHITE) << CGAL::RED; *m_window << CGAL::BackgroundColor(CGAL::white()) << CGAL::red();
(*m_window) << arr; (*m_window) << arr;
m_window->unlock(); m_window->unlock();
App->flush(); App->flush();
@ -490,9 +490,9 @@ public:
ps_stream.set_line_width(1); ps_stream.set_line_width(1);
CGAL::Arr_drawer<Arr, CGAL::Postscript_file_stream> drawer(ps_stream); CGAL::Arr_drawer<Arr, CGAL::Postscript_file_stream> drawer(ps_stream);
// drawer.draw_faces(arr.faces_begin(), arr.faces_end()); // drawer.draw_faces(arr.faces_begin(), arr.faces_end());
ps_stream << CGAL::BLUE; ps_stream << CGAL::blue();
drawer.draw_halfedges(arr.halfedges_begin(), arr.halfedges_end()); drawer.draw_halfedges(arr.halfedges_begin(), arr.halfedges_end());
ps_stream << CGAL::RED; ps_stream << CGAL::red();
drawer.draw_vertices(arr.vertices_begin(), arr.vertices_end()); drawer.draw_vertices(arr.vertices_begin(), arr.vertices_end());
// draw_arr(arr, drawer, ps_stream); // draw_arr(arr, drawer, ps_stream);

View File

@ -36,7 +36,6 @@
#endif #endif
#include <CGAL/Classification/Cluster.h> #include <CGAL/Classification/Cluster.h>
#include <CGAL/Classification/Color.h>
#include <CGAL/Classification/Evaluation.h> #include <CGAL/Classification/Evaluation.h>
#include <CGAL/Classification/Feature_base.h> #include <CGAL/Classification/Feature_base.h>
#include <CGAL/Classification/Feature_set.h> #include <CGAL/Classification/Feature_set.h>

View File

@ -1,140 +0,0 @@
// Copyright (c) 2017 GeometryFactory Sarl (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// 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 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0+
//
// Author(s) : Simon Giraudot
#ifndef CGAL_CLASSIFICATION_COLOR_H
#define CGAL_CLASSIFICATION_COLOR_H
#include <CGAL/license/Classification.h>
#include <CGAL/number_utils.h>
#include <CGAL/int.h>
#include <CGAL/array.h>
namespace CGAL {
namespace Classification {
/*!
\ingroup PkgClassificationColor
%Color described in red/green/blue space. Each component is stored
as an unsigned char ranging from 0 (no color) to 255 (full color).
*/
typedef std::array<unsigned char, 3> RGB_Color;
/*!
\ingroup PkgClassificationColor
%Color described in hue/saturation/value space. Each component is stored
as a float:
- `hue` ranges from 0° to 360° (corresponding to the color tint)
- `saturation` ranges from 0.0 (gray) to 100.0 (full saturation)
- `value` ranges from 0.0 (black) to 100.0 (white)
*/
typedef std::array<float, 3> HSV_Color;
/// \cond SKIP_IN_MANUAL
inline HSV_Color rgb_to_hsv (const RGB_Color& c)
{
double r = (double)(c[0]) / 255.;
double g = (double)(c[1]) / 255.;
double b = (double)(c[2]) / 255.;
double Cmax = (std::max) (r, (std::max) (g, b));
double Cmin = (std::min) (r, (std::min) (g, b));
double delta = Cmax - Cmin;
double H = 0.;
if (delta != 0.)
{
if (Cmax == r)
H = 60. * ((g - b) / delta);
else if (Cmax == g)
H = 60. * (((b - r) / delta) + 2.);
else
H = 60. * (((r - g) / delta) + 4.);
}
if (H < 0.) H += 360.;
double S = (Cmax == 0. ? 0. : 100. * (delta / Cmax));
double V = 100. * Cmax;
HSV_Color out = {{ float(H), float(S), float(V) }};
return out;
}
inline RGB_Color hsv_to_rgb (const HSV_Color& c)
{
double h = c[0];
double s = c[1];
double v = c[2];
s /= 100.;
v /= 100.;
double C = v*s;
int hh = (int)(h/60.);
double X = C * (1-CGAL::abs (hh % 2 - 1));
double r = 0, g = 0, b = 0;
if( hh>=0 && hh<1 )
{
r = C;
g = X;
}
else if( hh>=1 && hh<2 )
{
r = X;
g = C;
}
else if( hh>=2 && hh<3 )
{
g = C;
b = X;
}
else if( hh>=3 && hh<4 )
{
g = X;
b = C;
}
else if( hh>=4 && hh<5 )
{
r = X;
b = C;
}
else
{
r = C;
b = X;
}
double m = v-C;
r += m;
g += m;
b += m;
r *= 255.0;
g *= 255.0;
b *= 255.0;
RGB_Color out = {{ (unsigned char)r, (unsigned char)g, (unsigned char)b }};
return out;
}
/// \endcond
} // namespace Classification
} // namespace CGAL
#endif // CGAL_CLASSIFICATION_COLOR_H

View File

@ -25,8 +25,8 @@
#include <vector> #include <vector>
#include <CGAL/Classification/Color.h>
#include <CGAL/Classification/Feature_base.h> #include <CGAL/Classification/Feature_base.h>
#include <CGAL/array.h>
namespace CGAL { namespace CGAL {
@ -65,7 +65,7 @@ namespace Feature {
`ColorMap`. `ColorMap`.
\tparam ColorMap model of `ReadablePropertyMap` whose key \tparam ColorMap model of `ReadablePropertyMap` whose key
type is the value type of the iterator of `PointRange` and value type type is the value type of the iterator of `PointRange` and value type
is `CGAL::Classification::RGB_Color`. is `CGAL::Color`.
*/ */
template <typename GeomTraits, typename PointRange, typename ColorMap> template <typename GeomTraits, typename PointRange, typename ColorMap>
class Color_channel : public Feature_base class Color_channel : public Feature_base
@ -82,9 +82,6 @@ public:
private: private:
typedef typename Classification::RGB_Color RGB_Color;
typedef typename Classification::HSV_Color HSV_Color;
const PointRange& input; const PointRange& input;
ColorMap color_map; ColorMap color_map;
Channel m_channel; Channel m_channel;
@ -111,8 +108,8 @@ public:
/// \cond SKIP_IN_MANUAL /// \cond SKIP_IN_MANUAL
virtual float value (std::size_t pt_index) virtual float value (std::size_t pt_index)
{ {
HSV_Color c = Classification::rgb_to_hsv (get(color_map, *(input.begin()+pt_index))); cpp11::array<double, 3> c = get(color_map, *(input.begin()+pt_index)).to_hsv();
return c[std::size_t(m_channel)]; return float(c[std::size_t(m_channel)]);
} }
/// \endcond /// \endcond
}; };

View File

@ -1,431 +0,0 @@
// Copyright (c) 2017 GeometryFactory Sarl (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// 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 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0+
//
// Author(s) : Simon Giraudot
#ifndef CGAL_CLASSIFICATION_FEATURES_EIGEN_H
#define CGAL_CLASSIFICATION_FEATURES_EIGEN_H
#include <CGAL/license/Classification.h>
#include <vector>
#include <CGAL/Classification/Feature_base.h>
#include <CGAL/Classification/Local_eigen_analysis.h>
/// \cond SKIP_IN_MANUAL
#ifndef CGAL_NO_DEPRECATED_CODE
namespace CGAL {
namespace Classification {
namespace Feature {
class Eigen_feature : public Feature_base
{
protected:
#ifdef CGAL_CLASSIFICATION_PRECOMPUTE_FEATURES
std::vector<float> attrib;
#else
const Classification::Local_eigen_analysis& eigen;
#endif
public:
template <typename InputRange>
Eigen_feature (const InputRange&,
const Classification::Local_eigen_analysis& eigen)
#ifndef CGAL_CLASSIFICATION_PRECOMPUTE_FEATURES
: eigen (eigen)
#endif
{
}
#ifdef CGAL_CLASSIFICATION_PRECOMPUTE_FEATURES
virtual void init (std::size_t size, const Classification::Local_eigen_analysis& eigen)
{
attrib.reserve (size);
for (std::size_t i = 0; i < size; ++ i)
attrib.push_back (get_value (eigen, i));
}
#else
virtual void init (std::size_t, const Classification::Local_eigen_analysis&)
{
}
#endif
virtual float get_value (const Classification::Local_eigen_analysis& eigen, std::size_t i) = 0;
virtual float value (std::size_t pt_index)
{
#ifdef CGAL_CLASSIFICATION_PRECOMPUTE_FEATURES
return attrib[pt_index];
#else
return get_value(eigen, pt_index);
#endif
}
};
/*!
\ingroup PkgClassificationFeatures
%Feature based on the eigenvalues of the covariance matrix of a
local neighborhood. Linearity is defined, for the 3 eigenvalues
\f$\lambda_1 \ge \lambda_2 \ge \lambda_3 \ge 0\f$, as:
\f[
\frac{\lambda_1 - \lambda_2}{\lambda_1}
\f]
Its default name is "linearity".
*/
CGAL_DEPRECATED_MSG("you are using the deprecated feature Linearity, please update your code with Eigenvalue instead")
class Linearity
#ifdef DOXYGEN_RUNNING
: public Feature_base
#else
: public Eigen_feature
#endif
{
public:
/*!
Constructs the feature.
\tparam Input model of `ConstRange`. Its iterator type
is `RandomAccessIterator`.
\param input point range.
\param eigen class with precomputed eigenvectors and eigenvalues.
*/
template <typename InputRange>
Linearity (const InputRange& input,
const Local_eigen_analysis& eigen) : Eigen_feature (input, eigen)
{
this->set_name("linearity");
this->init(input.size(), eigen);
}
virtual float get_value (const Local_eigen_analysis& eigen, std::size_t i)
{
const Local_eigen_analysis::Eigenvalues& ev = eigen.eigenvalue(i);
if (ev[2] < 1e-15)
return 0.;
else
return ((ev[2] - ev[1]) / ev[2]);
}
};
/*!
\ingroup PkgClassificationFeatures
%Feature based on the eigenvalues of the covariance matrix of a
local neighborhood. Planarity is defined, for the 3 eigenvalues
\f$\lambda_1 \ge \lambda_2 \ge \lambda_3 \ge 0\f$, as:
\f[
\frac{\lambda_2 - \lambda_3}{\lambda_1}
\f]
Its default name is "planarity".
*/
CGAL_DEPRECATED_MSG("you are using the deprecated feature Planarity, please update your code with Eigenvalue instead")
class Planarity
#ifdef DOXYGEN_RUNNING
: public Feature_base
#else
: public Eigen_feature
#endif
{
public:
/*!
Constructs the feature.
\param input point range.
\param eigen class with precomputed eigenvectors and eigenvalues.
*/
template <typename InputRange>
Planarity (const InputRange& input,
const Local_eigen_analysis& eigen)
: Eigen_feature(input, eigen)
{
this->set_name("planarity");
this->init(input.size(), eigen);
}
virtual float get_value (const Local_eigen_analysis& eigen, std::size_t i)
{
const Local_eigen_analysis::Eigenvalues& ev = eigen.eigenvalue(i);
if (ev[2] < 1e-15)
return 0.;
else
return ((ev[1] - ev[0]) / ev[2]);
}
};
/*!
\ingroup PkgClassificationFeatures
%Feature based on the eigenvalues of the covariance matrix of a
local neighborhood. Sphericity is defined, for the 3 eigenvalues
\f$\lambda_1 \ge \lambda_2 \ge \lambda_3 \ge 0\f$, as:
\f[
\frac{\lambda_3}{\lambda_1}
\f]
Its default name is "sphericity".
*/
CGAL_DEPRECATED_MSG("you are using the deprecated feature Sphericity, please update your code with Eigenvalue instead")
class Sphericity
#ifdef DOXYGEN_RUNNING
: public Feature_base
#else
: public Eigen_feature
#endif
{
public:
/*!
Constructs the feature.
\param input point range.
\param eigen class with precomputed eigenvectors and eigenvalues.
*/
template <typename InputRange>
Sphericity (const InputRange& input,
const Local_eigen_analysis& eigen)
: Eigen_feature(input, eigen)
{
this->set_name("sphericity");
this->init(input.size(), eigen);
}
virtual float get_value (const Local_eigen_analysis& eigen, std::size_t i)
{
const Local_eigen_analysis::Eigenvalues& ev = eigen.eigenvalue(i);
if (ev[2] < 1e-15)
return 0.;
else
return (ev[0] / ev[2]);
}
};
/*!
\ingroup PkgClassificationFeatures
%Feature based on the eigenvalues of the covariance matrix of a
local neighborhood. Omnivariance is defined, for the 3 eigenvalues
\f$\lambda_1 \ge \lambda_2 \ge \lambda_3 \ge 0\f$, as:
\f[
(\lambda_1 \times \lambda_2 \times \lambda_3)^{\frac{1}{3}}
\f]
Its default name is "omnivariance".
*/
CGAL_DEPRECATED_MSG("you are using the deprecated feature Omnivariance, please update your code with Eigenvalue instead")
class Omnivariance
#ifdef DOXYGEN_RUNNING
: public Feature_base
#else
: public Eigen_feature
#endif
{
public:
/*!
Constructs the feature.
\param input point range.
\param eigen class with precomputed eigenvectors and eigenvalues.
*/
template <typename InputRange>
Omnivariance (const InputRange& input,
const Local_eigen_analysis& eigen)
: Eigen_feature(input, eigen)
{
this->set_name("omnivariance");
this->init(input.size(), eigen);
}
virtual float get_value (const Local_eigen_analysis& eigen, std::size_t i)
{
const Local_eigen_analysis::Eigenvalues& ev = eigen.eigenvalue(i);
return (std::pow (CGAL::abs(ev[0] * ev[1] * ev[2]), 0.333333333f));
}
};
/*!
\ingroup PkgClassificationFeatures
%Feature based on the eigenvalues of the covariance matrix of a
local neighborhood. Anisotropy is defined, for the 3 eigenvalues
\f$\lambda_1 \ge \lambda_2 \ge \lambda_3 \ge 0\f$, as:
\f[
\frac{\lambda_1 - \lambda_3}{\lambda_1}
\f]
Its default name is "anisotropy".
*/
CGAL_DEPRECATED_MSG("you are using the deprecated feature Anisotropy, please update your code with Eigenvalue instead")
class Anisotropy
#ifdef DOXYGEN_RUNNING
: public Feature_base
#else
: public Eigen_feature
#endif
{
public:
/*!
Constructs the feature.
\param input point range.
\param eigen class with precomputed eigenvectors and eigenvalues.
*/
template <typename InputRange>
Anisotropy (const InputRange& input,
const Local_eigen_analysis& eigen)
: Eigen_feature(input, eigen)
{
this->set_name("anisotropy");
this->init(input.size(), eigen);
}
virtual float get_value (const Local_eigen_analysis& eigen, std::size_t i)
{
const Local_eigen_analysis::Eigenvalues& ev = eigen.eigenvalue(i);
if (ev[2] < 1e-15)
return 0.;
else
return ((ev[2] - ev[0]) / ev[2]);
}
};
/*!
\ingroup PkgClassificationFeatures
%Feature based on the eigenvalues of the covariance matrix of a
local neighborhood. Eigentropy is defined, for the 3 eigenvalues
\f$\lambda_1 \ge \lambda_2 \ge \lambda_3 \ge 0\f$, as:
\f[
- \sum_{i=1}^3 \lambda_i \times \log{\lambda_i}
\f]
Its default name is "eigentropy".
*/
CGAL_DEPRECATED_MSG("you are using the deprecated feature Eigentropy, please update your code with Eigenvalue instead")
class Eigentropy
#ifdef DOXYGEN_RUNNING
: public Feature_base
#else
: public Eigen_feature
#endif
{
public:
/*!
Constructs the feature.
\param input point range.
\param eigen class with precomputed eigenvectors and eigenvalues.
*/
template <typename InputRange>
Eigentropy (const InputRange& input,
const Local_eigen_analysis& eigen)
: Eigen_feature(input, eigen)
{
this->set_name("eigentropy");
this->init(input.size(), eigen);
}
virtual float get_value (const Local_eigen_analysis& eigen, std::size_t i)
{
const Local_eigen_analysis::Eigenvalues& ev = eigen.eigenvalue(i);
if (ev[0] < 1e-15
|| ev[1] < 1e-15
|| ev[2] < 1e-15)
return 0.;
else
return (- ev[0] * std::log(ev[0])
- ev[1] * std::log(ev[1])
- ev[2] * std::log(ev[2]));
}
};
/*!
\ingroup PkgClassificationFeatures
%Feature based on the eigenvalues of the covariance
matrix of a local neighborhood. Surface variation is defined, for
the 3 eigenvalues \f$\lambda_1 \ge \lambda_2 \ge \lambda_3 \ge
0\f$, as:
\f[
\frac{\lambda_3}{\lambda_1 + \lambda_2 + \lambda_3}
\f]
Its default name is "surface_variation".
*/
CGAL_DEPRECATED_MSG("you are using the deprecated feature Surface_variation, please update your code with Eigenvalue instead")
class Surface_variation
#ifdef DOXYGEN_RUNNING
: public Feature_base
#else
: public Eigen_feature
#endif
{
public:
/*!
Constructs the feature.
\param input point range.
\param eigen class with precomputed eigenvectors and eigenvalues.
*/
template <typename InputRange>
Surface_variation (const InputRange& input,
const Local_eigen_analysis& eigen)
: Eigen_feature(input, eigen)
{
this->set_name("surface_variation");
this->init(input.size(), eigen);
}
virtual float get_value (const Local_eigen_analysis& eigen, std::size_t i)
{
const Local_eigen_analysis::Eigenvalues& ev = eigen.eigenvalue(i);
if (ev[0] + ev[1] + ev[2] < 1e-15)
return 0.;
else
return (ev[0] / (ev[0] + ev[1] + ev[2]));
}
};
} // namespace Feature
} // namespace Classification
} // namespace CGAL
#endif
/// \endcond
#endif // CGAL_CLASSIFICATION_FEATURES_EIGEN_H

View File

@ -1,175 +0,0 @@
// Copyright (c) 2017 GeometryFactory Sarl (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// 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 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0+
//
// Author(s) : Simon Giraudot
#ifndef CGAL_CLASSIFICATION_FEATURE_HSV_H
#define CGAL_CLASSIFICATION_FEATURE_HSV_H
#include <CGAL/license/Classification.h>
#include <vector>
#include <CGAL/Classification/Color.h>
#include <CGAL/Classification/Feature_base.h>
/// \cond SKIP_IN_MANUAL
#ifndef CGAL_NO_DEPRECATED_CODE
namespace CGAL {
namespace Classification {
namespace Feature {
/*!
\ingroup PkgClassificationFeatures
%Feature based on HSV colorimetric information. If the input
point cloud has colorimetric information, it can be used for
classification purposes. This feature is based on a Gaussian
probabilistic model on one of the three HSV channels (hue,
saturation or value). It computes the probability of the color of
the input point to match this specific color channel defined by a
mean and a standard deviation.
The HSV channels are defined this way:
- Hue ranges from 0 to 360 and measures the general "tint" of the
color (green, blue, pink, etc.)
- Saturation ranges from 0 to 100 and measures the "strength" of the
color (0 is gray and 100 is the fully saturated color)
- Value ranges from 0 to 100 and measures the "brightness" of the
color (0 is black and 100 is the fully bright color)
For example, such an feature using the channel 0 (hue) with a
mean of 90 (which corresponds to a green hue) can help to identify
trees.
\image html trees.png
<center><em>Left: input point set with colors. Right: HSV feature on hue with
a mean of 90 (from low values in white to high values in dark
red).</em></center>
Its default name is the channel followed by the mean value (for
example: "hue_180", "saturation_20" or "value_98").
\note The user only needs to provide a map to standard (and more common)
RGB colors, the conversion to HSV is done internally.
\tparam GeomTraits model of \cgal Kernel.
\tparam PointRange model of `ConstRange`. Its iterator type
is `RandomAccessIterator` and its value type is the key type of
`ColorMap`.
\tparam ColorMap model of `ReadablePropertyMap` whose key
type is the value type of the iterator of `PointRange` and value type
is `CGAL::Classification::RGB_Color`.
*/
template <typename GeomTraits, typename PointRange, typename ColorMap>
CGAL_DEPRECATED_MSG("you are using the deprecated feature Hsv, please update your code with Color_channel instead")
class Hsv : public Feature_base
{
public:
/// Selected channel.
enum Channel
{
HUE = 0, ///< 0
SATURATION = 1, ///< 1
VALUE = 2 ///< 2
};
private:
typedef typename Classification::RGB_Color RGB_Color;
typedef typename Classification::HSV_Color HSV_Color;
#ifdef CGAL_CLASSIFICATION_PRECOMPUTE_FEATURES
std::vector<float> color_feature;
#else
const PointRange& input;
ColorMap color_map;
Channel m_channel;
float m_mean;
float m_sd;
#endif
public:
/*!
\brief Constructs a feature based on the given color channel,
mean and standard deviation.
\param input point range.
\param color_map property map to access the colors of the input points.
\param channel chosen HSV channel.
\param mean mean value of the specified channel.
\param sd standard deviation of the specified channel.
*/
Hsv (const PointRange& input,
ColorMap color_map,
Channel channel,
float mean, float sd)
#ifndef CGAL_CLASSIFICATION_PRECOMPUTE_FEATURES
: input(input), color_map(color_map), m_channel(channel), m_mean(mean), m_sd(sd)
#endif
{
#ifdef CGAL_CLASSIFICATION_PRECOMPUTE_FEATURES
for(std::size_t i = 0; i < input.size();i++)
{
HSV_Color c = Classification::rgb_to_hsv (get(color_map, *(input.begin()+i)));
color_feature.push_back (std::exp (-(c[std::size_t(channel)] - mean)
* (c[std::size_t(channel)] - mean) / (2. * sd * sd)));
}
#endif
std::ostringstream oss;
if (channel == HUE) oss << "hue";
else if (channel == SATURATION) oss << "saturation";
else if (channel == VALUE) oss << "value";
oss << "_" << mean;
this->set_name (oss.str());
}
virtual float value (std::size_t pt_index)
{
#ifdef CGAL_CLASSIFICATION_PRECOMPUTE_FEATURES
return color_feature[pt_index];
#else
HSV_Color c = Classification::rgb_to_hsv (get(color_map, *(input.begin()+pt_index)));
return std::exp (-(c[std::size_t(m_channel)] - m_mean)
* (c[std::size_t(m_channel)] - m_mean) / (2.f * m_sd * m_sd));
#endif
}
};
} // namespace Feature
} // namespace Classification
} // namespace CGAL
#endif
/// \endcond
#endif // CGAL_CLASSIFICATION_FEATURE_HSV_H

View File

@ -152,8 +152,6 @@ public:
typedef Classification::Feature::Verticality typedef Classification::Feature::Verticality
<GeomTraits> Verticality; <GeomTraits> Verticality;
typedef Classification::Feature::Eigenvalue Eigenvalue; typedef Classification::Feature::Eigenvalue Eigenvalue;
typedef typename Classification::RGB_Color RGB_Color;
/// \endcond /// \endcond
private: private:

View File

@ -153,8 +153,6 @@ public:
typedef Classification::Feature::Gradient_of_feature typedef Classification::Feature::Gradient_of_feature
<PointRange, PointMap, Neighbor_query> Gradient_of_feature; <PointRange, PointMap, Neighbor_query> Gradient_of_feature;
#endif #endif
typedef typename Classification::RGB_Color RGB_Color;
/// \endcond /// \endcond
private: private:
@ -294,64 +292,6 @@ public:
/// @} /// @}
/// \cond SKIP_IN_MANUAL /// \cond SKIP_IN_MANUAL
#ifndef CGAL_NO_DEPRECATED_CODE
// deprecated
template <typename VectorMap = Default,
typename ColorMap = Default,
typename EchoMap = Default>
CGAL_DEPRECATED_MSG("you are using a deprecated constructor of CGAL::Classification::Point_set_feature_generator, please update your code")
Point_set_feature_generator(Feature_set& features,
const PointRange& input,
PointMap point_map,
std::size_t nb_scales,
VectorMap normal_map = VectorMap(),
ColorMap color_map = ColorMap(),
EchoMap echo_map = EchoMap(),
float voxel_size = -1.f)
: m_input (input), m_point_map (point_map)
{
m_bbox = CGAL::bounding_box
(boost::make_transform_iterator (m_input.begin(), CGAL::Property_map_to_unary_function<PointMap>(m_point_map)),
boost::make_transform_iterator (m_input.end(), CGAL::Property_map_to_unary_function<PointMap>(m_point_map)));
CGAL::Real_timer t; t.start();
m_scales.reserve (nb_scales);
m_scales.push_back (new Scale (m_input, m_point_map, m_bbox, voxel_size));
if (voxel_size == -1.f)
voxel_size = m_scales[0]->grid_resolution();
for (std::size_t i = 1; i < nb_scales; ++ i)
{
voxel_size *= 2;
m_scales.push_back (new Scale (m_input, m_point_map, m_bbox, voxel_size, m_scales[i-1]->grid));
}
t.stop();
CGAL_CLASSIFICATION_CERR << "Scales computed in " << t.time() << " second(s)" << std::endl;
t.reset();
typedef typename Default::Get<VectorMap, typename GeomTraits::Vector_3 >::type
Vmap;
typedef typename Default::Get<ColorMap, RGB_Color >::type
Cmap;
typedef typename Default::Get<EchoMap, std::size_t >::type
Emap;
generate_point_based_features (features);
generate_normal_based_features (features, get_parameter<Vmap>(normal_map));
generate_color_based_features (features, get_parameter<Cmap>(color_map));
generate_echo_based_features (features, get_parameter<Emap>(echo_map));
}
// Functions to remove when deprecated constructor is removed
void generate_normal_based_features(const CGAL::Constant_property_map<Iterator, typename GeomTraits::Vector_3>&) { }
void generate_color_based_features(const CGAL::Constant_property_map<Iterator, RGB_Color>&) { }
void generate_echo_based_features(const CGAL::Constant_property_map<Iterator, std::size_t>&) { }
#endif
virtual ~Point_set_feature_generator() virtual ~Point_set_feature_generator()
{ {
clear(); clear();
@ -434,7 +374,7 @@ public:
\tparam ColorMap model of `ReadablePropertyMap` whose key type is \tparam ColorMap model of `ReadablePropertyMap` whose key type is
the value type of the iterator of `PointRange` and value type is the value type of the iterator of `PointRange` and value type is
`CGAL::Classification::RGB_Color`. `CGAL::Color`.
\param features the feature set where the features are instantiated. \param features the feature set where the features are instantiated.
\param color_map property map to access the colors of the input points (if any). \param color_map property map to access the colors of the input points (if any).

View File

@ -89,14 +89,6 @@ if(TARGET test_classification_point_set)
endif() endif()
endif() endif()
create_single_source_cgal_program( "deprecated_test_classification_point_set.cpp" CXX_FEATURES ${needed_cxx_features} )
if(TARGET deprecated_test_classification_point_set)
target_link_libraries(deprecated_test_classification_point_set PUBLIC ${classification_linked_libraries})
if (TBB_FOUND)
CGAL_target_use_TBB( deprecated_test_classification_point_set )
endif()
endif()
create_single_source_cgal_program( "test_classification_io.cpp" CXX_FEATURES ${needed_cxx_features} ) create_single_source_cgal_program( "test_classification_io.cpp" CXX_FEATURES ${needed_cxx_features} )
if(TARGET test_classification_io) if(TARGET test_classification_io)
target_link_libraries(test_classification_io PUBLIC ${classification_linked_libraries}) target_link_libraries(test_classification_io PUBLIC ${classification_linked_libraries})

View File

@ -1,136 +0,0 @@
#include <CGAL/internal/disable_deprecation_warnings_and_errors.h>
#if defined (_MSC_VER) && !defined (_WIN64)
#pragma warning(disable:4244) // boost::number_distance::distance()
// converts 64 to 32 bits integers
#endif
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Classification.h>
#include <CGAL/Point_set_3.h>
#include <CGAL/Random.h>
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point;
typedef Kernel::Vector_3 Vector;
typedef CGAL::Point_set_3<Point> Point_set;
typedef Point_set::Point_map Point_map;
typedef Kernel::Iso_cuboid_3 Iso_cuboid_3;
namespace Classification = CGAL::Classification;
typedef Classification::Label_handle Label_handle;
typedef Classification::Feature_handle Feature_handle;
typedef Classification::Label_set Label_set;
typedef Classification::Feature_set Feature_set;
typedef Classification::Sum_of_weighted_features_classifier Classifier;
typedef Classification::Point_set_feature_generator<Kernel, Point_set, Point_map> Feature_generator;
typedef Point_set::Property_map<std::size_t> Size_t_map;
typedef Point_set::Property_map<Classification::RGB_Color> Color_map;
int main (int, char**)
{
Point_set pts;
pts.add_normal_map();
bool map_added = false;
Size_t_map echo_map;
Color_map color_map;
boost::tie (echo_map, map_added) = pts.add_property_map<std::size_t> ("echo");
assert (map_added);
boost::tie (color_map, map_added) = pts.add_property_map<Classification::RGB_Color> ("color");
assert (map_added);
for (std::size_t i = 0; i < 1000; ++ i)
{
Point_set::iterator it
= pts.insert (Point (CGAL::get_default_random().get_double(),
CGAL::get_default_random().get_double(),
CGAL::get_default_random().get_double()),
Vector (CGAL::get_default_random().get_double(),
CGAL::get_default_random().get_double(),
CGAL::get_default_random().get_double()));
echo_map[*it] = std::size_t(CGAL::get_default_random().get_int(0, 4));
color_map[*it] = CGAL::make_array ((unsigned char)(CGAL::get_default_random().get_int(0, 255)),
(unsigned char)(CGAL::get_default_random().get_int(0, 255)),
(unsigned char)(CGAL::get_default_random().get_int(0, 255)));
}
Feature_set features;
Feature_generator generator (features, pts, pts.point_map(),
5, // using 5 scales
pts.normal_map(),
color_map, echo_map);
assert (generator.number_of_scales() == 5);
assert (features.size() == 59);
Label_set labels;
std::vector<int> training_set (pts.size(), -1);
for (std::size_t i = 0; i < 20; ++ i)
{
std::ostringstream oss;
oss << "label_" << i;
Label_handle lh = labels.add(oss.str().c_str());
for (std::size_t j = 0; j < 10; ++ j)
training_set[std::size_t(CGAL::get_default_random().get_int(0, int(training_set.size())))] = int(i);
}
assert (labels.size() == 20);
Classifier classifier (labels, features);
classifier.train<CGAL::Sequential_tag> (training_set, 800);
#ifdef CGAL_LINKED_WITH_TBB
classifier.train<CGAL::Parallel_tag> (training_set, 800);
#endif
std::vector<int> label_indices(pts.size(), -1);
Classification::classify<CGAL::Sequential_tag>
(pts, labels, classifier, label_indices);
Classification::classify_with_local_smoothing<CGAL::Sequential_tag>
(pts, pts.point_map(), labels, classifier,
generator.neighborhood().sphere_neighbor_query(0.01f),
label_indices);
Classification::classify_with_graphcut<CGAL::Sequential_tag>
(pts, pts.point_map(), labels, classifier,
generator.neighborhood().k_neighbor_query(12),
0.2f, 10, label_indices);
#ifdef CGAL_LINKED_WITH_TBB
Classification::classify<CGAL::Sequential_tag>
(pts, labels, classifier, label_indices);
Classification::classify_with_local_smoothing<CGAL::Sequential_tag>
(pts, pts.point_map(), labels, classifier,
generator.neighborhood().sphere_neighbor_query(0.01f),
label_indices);
Classification::classify_with_graphcut<CGAL::Sequential_tag>
(pts, pts.point_map(), labels, classifier,
generator.neighborhood().k_neighbor_query(12),
0.2f, 10, label_indices);
#endif
Classification::Evaluation evaluation (labels, training_set, label_indices);
return EXIT_SUCCESS;
}

View File

@ -37,7 +37,7 @@ typedef Classification::Point_set_feature_generator<Kernel, Point_set, Point_map
typedef Point_set::Vector_map Vector_map; typedef Point_set::Vector_map Vector_map;
typedef Point_set::Property_map<std::size_t> Size_t_map; typedef Point_set::Property_map<std::size_t> Size_t_map;
typedef Point_set::Property_map<Classification::RGB_Color> Color_map; typedef Point_set::Property_map<CGAL::Color> Color_map;
@ -55,7 +55,7 @@ int main (int, char**)
normal_map = pts.normal_map(); normal_map = pts.normal_map();
boost::tie (echo_map, map_added) = pts.add_property_map<std::size_t> ("echo"); boost::tie (echo_map, map_added) = pts.add_property_map<std::size_t> ("echo");
assert (map_added); assert (map_added);
boost::tie (color_map, map_added) = pts.add_property_map<Classification::RGB_Color> ("color"); boost::tie (color_map, map_added) = pts.add_property_map<CGAL::Color> ("color");
assert (map_added); assert (map_added);
for (std::size_t i = 0; i < 1000; ++ i) for (std::size_t i = 0; i < 1000; ++ i)
@ -68,9 +68,9 @@ int main (int, char**)
CGAL::get_default_random().get_double(), CGAL::get_default_random().get_double(),
CGAL::get_default_random().get_double())); CGAL::get_default_random().get_double()));
echo_map[*it] = std::size_t(CGAL::get_default_random().get_int(0, 4)); echo_map[*it] = std::size_t(CGAL::get_default_random().get_int(0, 4));
color_map[*it] = CGAL::make_array ((unsigned char)(CGAL::get_default_random().get_int(0, 255)), color_map[*it] = CGAL::Color ((unsigned char)(CGAL::get_default_random().get_int(0, 255)),
(unsigned char)(CGAL::get_default_random().get_int(0, 255)), (unsigned char)(CGAL::get_default_random().get_int(0, 255)),
(unsigned char)(CGAL::get_default_random().get_int(0, 255))); (unsigned char)(CGAL::get_default_random().get_int(0, 255)));
} }
Feature_set features; Feature_set features;

View File

@ -67,7 +67,7 @@ void draw_points_and_hull(const std::vector<Point_3>& points,
std::vector<Point_3>::const_iterator p_it; std::vector<Point_3>::const_iterator p_it;
CGAL::Geomview_stream geomview; CGAL::Geomview_stream geomview;
geomview << CGAL::RED; geomview << CGAL::red();
for (p_it = points.begin(); p_it != points.end(); p_it++) for (p_it = points.begin(); p_it != points.end(); p_it++)
{ {
geomview << *p_it; geomview << *p_it;
@ -78,7 +78,7 @@ void draw_points_and_hull(const std::vector<Point_3>& points,
Point_3 point; Point_3 point;
Polyhedron_3 polyhedron; Polyhedron_3 polyhedron;
geomview << CGAL::BLUE; geomview << CGAL::blue();
if ( CGAL::assign(point, object) ) if ( CGAL::assign(point, object) )
geomview << point; geomview << point;
else if ( CGAL::assign(segment, object) ) else if ( CGAL::assign(segment, object) )

View File

@ -57,13 +57,13 @@ int main()
// use different colors, and put a few sleeps/clear. // use different colors, and put a few sleeps/clear.
gv << CGAL::BLUE; gv << CGAL::blue();
std::cout << "Drawing 2D Delaunay triangulation in wired mode.\n"; std::cout << "Drawing 2D Delaunay triangulation in wired mode.\n";
gv.set_wired(true); gv.set_wired(true);
gv << D; gv << D;
#if 1 // It's too slow ! Needs to use OFF for that. #if 1 // It's too slow ! Needs to use OFF for that.
gv << CGAL::RED; gv << CGAL::red();
std::cout << "Drawing its Voronoi diagram.\n"; std::cout << "Drawing its Voronoi diagram.\n";
gv.set_wired(true); gv.set_wired(true);
D.draw_dual(gv); D.draw_dual(gv);

View File

@ -50,25 +50,25 @@ int main()
gv.clear(); // remove the pickplane. gv.clear(); // remove the pickplane.
gv << K::Point_2 (200, 100); gv << K::Point_2 (200, 100);
gv << CGAL::BLUE; gv << CGAL::blue();
gv << K::Point_3 (200, 100, 100); gv << K::Point_3 (200, 100, 100);
gv << CGAL::RED; gv << CGAL::red();
gv << K::Segment_2 (K::Point_2(200, 100), gv << K::Segment_2 (K::Point_2(200, 100),
K::Point_2(300, 100)); K::Point_2(300, 100));
gv << CGAL::GREEN; gv << CGAL::green();
gv << K::Segment_3 (K::Point_3(200, 100, 100), gv << K::Segment_3 (K::Point_3(200, 100, 100),
K::Point_3(300, 100, 200)); K::Point_3(300, 100, 200));
gv << CGAL::DEEPBLUE; gv << CGAL::deep_blue();
gv << K::Sphere_3 (K::Point_3(100, 100, 100), 1000); gv << K::Sphere_3 (K::Point_3(100, 100, 100), 1000);
gv << CGAL::VIOLET; gv << CGAL::violet();
gv << K::Triangle_2 (K::Point_2(200, 200), gv << K::Triangle_2 (K::Point_2(200, 200),
K::Point_2(220, 220), K::Point_2(220, 220),
K::Point_2(180, 220)); K::Point_2(180, 220));
gv << CGAL::ORANGE; gv << CGAL::orange();
gv << K::Triangle_3 (K::Point_3(200, 200, 50), gv << K::Triangle_3 (K::Point_3(200, 200, 50),
K::Point_3(220, 220, 80), K::Point_3(220, 220, 80),
K::Point_3(180, 220, 100)); K::Point_3(180, 220, 100));
gv << CGAL::PURPLE; gv << CGAL::purple();
gv << K::Tetrahedron_3 (K::Point_3(100, 100, 180), gv << K::Tetrahedron_3 (K::Point_3(100, 100, 180),
K::Point_3(120, 70, 220), K::Point_3(120, 70, 220),
K::Point_3(100, 100, 220), K::Point_3(100, 100, 220),
@ -76,7 +76,7 @@ int main()
gv << CGAL::Bbox_2(10, 10, 30, 30); gv << CGAL::Bbox_2(10, 10, 30, 30);
gv << CGAL::Bbox_3(10, 10, 10, 30, 30, 30); gv << CGAL::Bbox_3(10, 10, 10, 30, 30, 30);
gv << CGAL::RED; gv << CGAL::red();
gv << K::Ray_2(K::Point_2(205,205), K::Point_2(500,500)); gv << K::Ray_2(K::Point_2(205,205), K::Point_2(500,500));
gv << K::Ray_3(K::Point_3(250,250,250), K::Point_3(500,500,500)); gv << K::Ray_3(K::Point_3(250,250,250), K::Point_3(500,500,500));
gv << K::Line_2(K::Point_2(195,195), K::Point_2(500,500)); gv << K::Line_2(K::Point_2(195,195), K::Point_2(500,500));

View File

@ -49,7 +49,7 @@ CGAL_INLINE_FUNCTION
Geomview_stream::Geomview_stream(const Bbox_3 &bbox, Geomview_stream::Geomview_stream(const Bbox_3 &bbox,
const char *machine, const char *machine,
const char *login) const char *login)
: bb(bbox), vertex_color(BLACK), edge_color(BLACK), face_color(BLACK), : bb(bbox), vertex_color(black()), edge_color(black()), face_color(black()),
wired_flag(false), echo_flag(true), raw_flag(false), wired_flag(false), echo_flag(true), raw_flag(false),
trace_flag(false), binary_flag(false), trace_flag(false), binary_flag(false),
line_width(1) line_width(1)

View File

@ -173,9 +173,9 @@ SegmentDelaunayGraphGraphicsItem<T>::drawAll(QPainter *painter, const QStyleOpti
vit != t->finite_vertices_end(); ++vit) { vit != t->finite_vertices_end(); ++vit) {
typename T::Site_2 s = vit->site(); typename T::Site_2 s = vit->site();
if ( s.is_input() ) { if ( s.is_input() ) {
//*widget << CGAL::RED; //*widget << CGAL::red();
} else { } else {
//*widget << CGAL::YELLOW; //*widget << CGAL::yellow();
} }
if ( s.is_point() ) { if ( s.is_point() ) {
QPointF point = matrix.map(convert(s.point())); QPointF point = matrix.map(convert(s.point()));

View File

@ -208,9 +208,9 @@ SegmentDelaunayGraphLinfGraphicsItem<T>::drawAll(QPainter *painter, const QStyle
vit != t->finite_vertices_end(); ++vit) { vit != t->finite_vertices_end(); ++vit) {
typename T::Site_2 s = vit->site(); typename T::Site_2 s = vit->site();
if ( s.is_input() ) { if ( s.is_input() ) {
//*widget << CGAL::RED; //*widget << CGAL::red();
} else { } else {
//*widget << CGAL::YELLOW; //*widget << CGAL::yellow();
} }
if ( s.is_point() ) { if ( s.is_point() ) {
QPointF point = matrix.map(convert(s.point())); QPointF point = matrix.map(convert(s.point()));

View File

@ -28,8 +28,8 @@ typedef HDS::Face_handle Face_handle;
int main() { int main() {
HDS hds; HDS hds;
Face_handle f = hds.faces_push_back( Face( CGAL::RED)); Face_handle f = hds.faces_push_back( Face( CGAL::red()));
f->color = CGAL::BLUE; f->color = CGAL::blue();
CGAL_assertion( f->color == CGAL::BLUE); CGAL_assertion( f->color == CGAL::blue());
return 0; return 0;
} }

View File

@ -1,10 +1,9 @@
// Use something defined not in headers but in the CGAL library to test that is was indeed properly built and linked to, // Use something defined not in headers but in the CGAL library to test that is was indeed properly built and linked to,
#include <CGAL/IO/Color.h> #include <CGAL/Random.h>
int main() int main()
{ {
volatile const CGAL::Color* c = &CGAL::BLACK; volatile const CGAL::Random* r = &CGAL::get_default_random();
return int(r != 0);
return (c != 0) ? 0 : 1;
} }

View File

@ -287,14 +287,14 @@ int main(int , char** )
std::cout << "The data points are displayed in blue in the geomview" std::cout << "The data points are displayed in blue in the geomview"
<< " application." << std::endl; << " application." << std::endl;
gv << CGAL::BLUE; gv << CGAL::blue();
visu_points(gv,sample_3); visu_points(gv,sample_3);
//show the gradients //show the gradients
if(method>0){ if(method>0){
std::cout << "The function gradients are displayed by red lines " std::cout << "The function gradients are displayed by red lines "
<<" in the geomview application." << std::endl; <<" in the geomview application." << std::endl;
gv <<CGAL::RED; gv <<CGAL::red();
gv << Segment_3(Point_3(h/3,h/3,w),Point_3(h/3,h/3,w)+ Vector_3(-g,-g,0)); gv << Segment_3(Point_3(h/3,h/3,w),Point_3(h/3,h/3,w)+ Vector_3(-g,-g,0));
gv << Segment_3(Point_3(-h/3,h/3,w),Point_3(-h/3,h/3,w)+Vector_3(g,-g,0)); gv << Segment_3(Point_3(-h/3,h/3,w),Point_3(-h/3,h/3,w)+Vector_3(g,-g,0));
gv << Segment_3(Point_3(-h/3,-h/3,w),Point_3(-h/3,-h/3,w)+Vector_3(g,g,0)); gv << Segment_3(Point_3(-h/3,-h/3,w),Point_3(-h/3,-h/3,w)+Vector_3(g,g,0));

View File

@ -217,21 +217,21 @@ int main()
} }
char ch; char ch;
gv << CGAL::VIOLET; gv << CGAL::violet();
visu_points(gv,points); visu_points(gv,points);
gv << CGAL::RED << Segment(p, p+ 0.3*normal); gv << CGAL::red() << Segment(p, p+ 0.3*normal);
gv << CGAL::ORANGE <<p; gv << CGAL::orange() <<p;
std::cout << "Visualizing the intersection of " std::cout << "Visualizing the intersection of "
<< "3D Voronoi diagram with tangent plane at " << "3D Voronoi diagram with tangent plane at "
<< p << "." << std::endl; << p << "." << std::endl;
gv << CGAL::BLUE; gv << CGAL::blue();
T.draw_dual(gv); T.draw_dual(gv);
Face_iterator fit = T.finite_faces_begin(), Face_iterator fit = T.finite_faces_begin(),
fend = T.finite_faces_end(); fend = T.finite_faces_end();
for(;fit != fend;fit++) for(;fit != fend;fit++)
gv <<CGAL::BLACK<<T.dual(fit); gv <<CGAL::black()<<T.dual(fit);
std::cout << "Enter any character to quit" << std::endl; std::cout << "Enter any character to quit" << std::endl;
std::cin >> ch; std::cin >> ch;

View File

@ -174,7 +174,7 @@ void output_distribution_to_png(std::vector<double>& elements,
const double scale = double_options["scale"]; const double scale = double_options["scale"];
*widget << CGAL::FillColor(CGAL::BLACK); *widget << CGAL::FillColor(CGAL::black());
// *widget << Segment_2(Point_2(0., 0.), Point_2(1., 0.)); // *widget << Segment_2(Point_2(0., 0.), Point_2(1., 0.));
for(int k=0;k<number_of_classes;k++) for(int k=0;k<number_of_classes;k++)
if(distribution[k]>0) if(distribution[k]>0)
@ -184,12 +184,12 @@ void output_distribution_to_png(std::vector<double>& elements,
height = ( (distribution[k]+0.)/number_of_cells ) * scale; height = ( (distribution[k]+0.)/number_of_cells ) * scale;
else else
height = ( std::log(distribution[k]+0.)/std::log(number_of_cells) ) * (-scale); height = ( std::log(distribution[k]+0.)/std::log(number_of_cells) ) * (-scale);
*widget << CGAL::BLACK *widget << CGAL::black()
<< Rectangle_2(Point_2(k*width, 0), << Rectangle_2(Point_2(k*width, 0),
Point_2((k+1)*width, height)); Point_2((k+1)*width, height));
} }
else else
*widget << CGAL::RED << Segment_2(Point_2(k*width, 0), *widget << CGAL::red() << Segment_2(Point_2(k*width, 0),
Point_2((k+1)*width, 0)); Point_2((k+1)*width, 0));
widget->unlock(); widget->unlock();

View File

@ -34,10 +34,10 @@ void display_distribution(Distribution_displayer* display,
const double height = ( distribution[k]+0. ) * echelle; const double height = ( distribution[k]+0. ) * echelle;
display->fill_rectangle(k * width, 0, display->fill_rectangle(k * width, 0,
(k+1)* width, height, (k+1)* width, height,
CGAL::BLACK); CGAL::black());
} }
else else
display->segment(k * width, 0., display->segment(k * width, 0.,
(k+1) * width, 0., (k+1) * width, 0.,
CGAL::RED); CGAL::red());
} }

View File

@ -99,7 +99,7 @@ bool process_aux_2(const std::vector<Qualities>& qualities,
displays[i]->segment(x_position_of_length_bound, 0.0, displays[i]->segment(x_position_of_length_bound, 0.0,
x_position_of_length_bound, -0.05, x_position_of_length_bound, -0.05,
CGAL::BLUE); CGAL::blue());
} }
*out_stream << "saving " << filename.c_str() << "...\n"; *out_stream << "saving " << filename.c_str() << "...\n";

View File

@ -180,7 +180,7 @@ void parse_argv(int argc, char** argv, int extra_args = 0)
// //
// const double scale = double_options["scale"]; // const double scale = double_options["scale"];
// //
//// *widget << CGAL::FillColor(CGAL::BLACK); //// *widget << CGAL::FillColor(CGAL::black());
// // *widget << Segment_2(Point_2(0., 0.), Point_2(1., 0.)); // // *widget << Segment_2(Point_2(0., 0.), Point_2(1., 0.));
// for(int k=0;k<number_of_classes;k++) // for(int k=0;k<number_of_classes;k++)
// if(distribution[k]>0) // if(distribution[k]>0)
@ -190,12 +190,12 @@ void parse_argv(int argc, char** argv, int extra_args = 0)
// height = ( (distribution[k]+0.)/number_of_cells ) * scale; // height = ( (distribution[k]+0.)/number_of_cells ) * scale;
// else // else
// height = ( std::log(distribution[k]+0.)/std::log(number_of_cells) ) * (-scale); // height = ( std::log(distribution[k]+0.)/std::log(number_of_cells) ) * (-scale);
//// *widget << CGAL::BLACK //// *widget << CGAL::black()
//// << Rectangle_2(Point_2(k*width, 0), //// << Rectangle_2(Point_2(k*width, 0),
//// Point_2((k+1)*width, height)); //// Point_2((k+1)*width, height));
// } // }
// else // else
//// *widget << CGAL::RED << Segment_2(Point_2(k*width, 0), //// *widget << CGAL::red() << Segment_2(Point_2(k*width, 0),
//// Point_2((k+1)*width, 0)); //// Point_2((k+1)*width, 0));
// //
// // widget->unlock(); // // widget->unlock();

View File

@ -48,11 +48,11 @@ class SNC_SM_BooleColor
typedef typename Refs_::Mark Mark; typedef typename Refs_::Mark Mark;
public: public:
Color color(SVertex_const_handle, Mark m) const Color color(SVertex_const_handle, Mark m) const
{ return ( m ? CGAL::BLACK : CGAL::WHITE ); } { return ( m ? CGAL::black() : CGAL::white() ); }
Color color(SHalfedge_const_handle, Mark m) const Color color(SHalfedge_const_handle, Mark m) const
{ return ( m ? CGAL::BLACK : CGAL::WHITE ); } { return ( m ? CGAL::black() : CGAL::white() ); }
Color color(SHalfloop_const_handle, Mark m) const Color color(SHalfloop_const_handle, Mark m) const
{ return ( m ? CGAL::BLACK : CGAL::WHITE ); } { return ( m ? CGAL::black() : CGAL::white() ); }
Color color(SFace_const_handle, Mark m) const Color color(SFace_const_handle, Mark m) const
{ return ( m ? CGAL_NEF3_DGREY : CGAL_NEF3_LGREY ); } { return ( m ? CGAL_NEF3_DGREY : CGAL_NEF3_LGREY ); }
}; };

View File

@ -48,11 +48,11 @@ class SNC_SM_BooleColor
typedef typename Map_::Mark Mark; typedef typename Map_::Mark Mark;
public: public:
Color color(SVertex_const_handle, Mark m) const Color color(SVertex_const_handle, Mark m) const
{ return ( m ? CGAL::BLACK : CGAL::WHITE ); } { return ( m ? CGAL::black() : CGAL::white() ); }
Color color(SHalfedge_const_handle, Mark m) const Color color(SHalfedge_const_handle, Mark m) const
{ return ( m ? CGAL::BLACK : CGAL::WHITE ); } { return ( m ? CGAL::black() : CGAL::white() ); }
Color color(SHalfloop_const_handle, Mark m) const Color color(SHalfloop_const_handle, Mark m) const
{ return ( m ? CGAL::BLACK : CGAL::WHITE ); } { return ( m ? CGAL::black() : CGAL::white() ); }
Color color(SFace_const_handle, Mark m) const Color color(SFace_const_handle, Mark m) const
{ return ( m ? CGAL_NEF_DGREY : CGAL_NEF_LGREY ); } { return ( m ? CGAL_NEF_DGREY : CGAL_NEF_LGREY ); }
}; };

View File

@ -44,11 +44,11 @@ class SM_BooleColor
typedef typename Map_::Mark Mark; typedef typename Map_::Mark Mark;
public: public:
Color color(SVertex_const_handle, Mark m) const Color color(SVertex_const_handle, Mark m) const
{ return ( m ? CGAL::BLACK : CGAL::WHITE ); } { return ( m ? CGAL::black() : CGAL::white() ); }
Color color(SHalfedge_const_handle, Mark m) const Color color(SHalfedge_const_handle, Mark m) const
{ return ( m ? CGAL::BLACK : CGAL::WHITE ); } { return ( m ? CGAL::black() : CGAL::white() ); }
Color color(SHalfloop_const_handle, Mark m) const Color color(SHalfloop_const_handle, Mark m) const
{ return ( m ? CGAL::BLACK : CGAL::WHITE ); } { return ( m ? CGAL::black() : CGAL::white() ); }
Color color(SFace_const_handle, Mark m) const Color color(SFace_const_handle, Mark m) const
{ return ( m ? CGAL_NEF_DGREY : CGAL_NEF_LGREY ); } { return ( m ? CGAL_NEF_DGREY : CGAL_NEF_LGREY ); }
}; };

View File

@ -254,7 +254,7 @@ class Sphere_point : public VPoint, public Gen_object {
public: public:
Sphere_point() {} Sphere_point() {}
Sphere_point(const CGAL::Sphere_point<R>& p, Sphere_point(const CGAL::Sphere_point<R>& p,
CGAL::Color c = CGAL::BLACK, unsigned w = 10) : CGAL::Color c = CGAL::black(), unsigned w = 10) :
VPoint(Approximator<R>::approximate(p)), p_(p), c_(c), w_(w) {} VPoint(Approximator<R>::approximate(p)), p_(p), c_(c), w_(w) {}
Sphere_point(const Sphere_point<R>& p) : VPoint(p), Gen_object() Sphere_point(const Sphere_point<R>& p) : VPoint(p), Gen_object()
{ p_ = p.p_; c_ = p.c_; w_ = p.w_; } { p_ = p.p_; c_ = p.c_; w_ = p.w_; }
@ -297,7 +297,7 @@ class Sphere_segment : public VSegment, public Gen_object {
public: public:
Sphere_segment() {} Sphere_segment() {}
Sphere_segment(const CGAL::Sphere_segment<R>& s, Sphere_segment(const CGAL::Sphere_segment<R>& s,
CGAL::Color c = CGAL::BLACK, unsigned w = 2) CGAL::Color c = CGAL::black(), unsigned w = 2)
: VSegment(Approximator<R>::approximate(s)), s_(s), c_(c), w_(w) {} : VSegment(Approximator<R>::approximate(s)), s_(s), c_(c), w_(w) {}
Sphere_segment(const Sphere_segment<R>& s) : VSegment(s), Gen_object() Sphere_segment(const Sphere_segment<R>& s) : VSegment(s), Gen_object()
{ s_ = s.s_; c_ = s.c_; w_ = s.w_; } { s_ = s.s_; c_ = s.c_; w_ = s.w_; }
@ -350,7 +350,7 @@ class Sphere_circle : public VSegment, public Gen_object {
public: public:
Sphere_circle() {} Sphere_circle() {}
Sphere_circle(const CGAL::Sphere_circle<R>& s, Sphere_circle(const CGAL::Sphere_circle<R>& s,
CGAL::Color c = CGAL::BLACK, unsigned w = 2) CGAL::Color c = CGAL::black(), unsigned w = 2)
: VSegment(Approximator<R>::approximate(s)), s_(s), c_(c), w_(w) {} : VSegment(Approximator<R>::approximate(s)), s_(s), c_(c), w_(w) {}
Sphere_circle(const Sphere_circle<R>& s) : VSegment(s), Gen_object() Sphere_circle(const Sphere_circle<R>& s) : VSegment(s), Gen_object()
{ s_ = s.s_; c_ = s.c_; w_ = s.w_; } { s_ = s.s_; c_ = s.c_; w_ = s.w_; }
@ -539,27 +539,27 @@ Unit_sphere& operator=(const Unit_sphere& S)
template <typename R> template <typename R>
void push_back(const CGAL::Sphere_point<R>& p, void push_back(const CGAL::Sphere_point<R>& p,
CGAL::Color c = CGAL::YELLOW, unsigned w = 5) CGAL::Color c = CGAL::yellow(), unsigned w = 5)
{ objects_.push_back(new Sphere_point<R>(p,c,w)); } { objects_.push_back(new Sphere_point<R>(p,c,w)); }
template <typename R> template <typename R>
void push_back(const CGAL::Sphere_segment<R>& s, void push_back(const CGAL::Sphere_segment<R>& s,
CGAL::Color c = CGAL::BLACK, unsigned w = 1) CGAL::Color c = CGAL::black(), unsigned w = 1)
{ objects_.push_back(new Sphere_segment<R>(s,c,w)); } { objects_.push_back(new Sphere_segment<R>(s,c,w)); }
template <typename R> template <typename R>
void push_back(const CGAL::Sphere_circle<R>& s, void push_back(const CGAL::Sphere_circle<R>& s,
CGAL::Color c = CGAL::BLACK, unsigned w = 1) CGAL::Color c = CGAL::black(), unsigned w = 1)
{ objects_.push_back(new Sphere_circle<R>(s,c,w)); } { objects_.push_back(new Sphere_circle<R>(s,c,w)); }
template <typename R> template <typename R>
void push_back(const CGAL::Sphere_triangle<R>& t, void push_back(const CGAL::Sphere_triangle<R>& t,
CGAL::Color c = CGAL::WHITE) CGAL::Color c = CGAL::white())
{ triangles_.push_back(new Sphere_triangle<R>(t,c)); } { triangles_.push_back(new Sphere_triangle<R>(t,c)); }
template <typename R> template <typename R>
void push_back_triangle_edge(const CGAL::Sphere_segment<R>& s, void push_back_triangle_edge(const CGAL::Sphere_segment<R>& s,
CGAL::Color c = CGAL::BLUE, unsigned w = 1) CGAL::Color c = CGAL::blue(), unsigned w = 1)
{ triangle_edges_.push_back(new Sphere_segment<R>(s,c,w)); } { triangle_edges_.push_back(new Sphere_segment<R>(s,c,w)); }
void set_style(int style) { void set_style(int style) {
@ -718,11 +718,11 @@ class SM_BooleColor
typedef typename Map_::Mark Mark; typedef typename Map_::Mark Mark;
public: public:
Color color(SVertex_const_handle, Mark m) const Color color(SVertex_const_handle, Mark m) const
{ return ( m ? CGAL::BLACK : CGAL::WHITE ); } { return ( m ? CGAL::black() : CGAL::white() ); }
Color color(SHalfedge_const_handle, Mark m) const Color color(SHalfedge_const_handle, Mark m) const
{ return ( m ? CGAL::BLACK : CGAL::WHITE ); } { return ( m ? CGAL::black() : CGAL::white() ); }
Color color(SHalfloop_const_handle, Mark m) const Color color(SHalfloop_const_handle, Mark m) const
{ return ( m ? CGAL::BLACK : CGAL::WHITE ); } { return ( m ? CGAL::black() : CGAL::white() ); }
Color color(SFace_const_handle, Mark m) const Color color(SFace_const_handle, Mark m) const
{ return ( m ? CGAL_NEF_DGREY : CGAL_NEF_LGREY ); } { return ( m ? CGAL_NEF_DGREY : CGAL_NEF_LGREY ); }
}; };

View File

@ -32,7 +32,7 @@ int main()
PDT::Vertex_iterator vit; PDT::Vertex_iterator vit;
for (vit = T.vertices_begin(); vit != T.vertices_end(); ++vit) for (vit = T.vertices_begin(); vit != T.vertices_end(); ++vit)
if (T.degree(vit) == 6) if (T.degree(vit) == 6)
vit->info() = CGAL::RED; vit->info() = CGAL::red();
return 0; return 0;
} }

View File

@ -36,7 +36,7 @@ int main(int, char**)
P3DT3::Vertex_iterator vit; P3DT3::Vertex_iterator vit;
for (vit = T.vertices_begin(); vit != T.vertices_end(); ++vit) { for (vit = T.vertices_begin(); vit != T.vertices_end(); ++vit) {
if (T.degree(vit) == 16) { if (T.degree(vit) == 16) {
vit->info() = CGAL::RED; vit->info() = CGAL::red();
} }
} }

View File

@ -35,87 +35,12 @@
#include <CGAL/IO/read_las_points.h> #include <CGAL/IO/read_las_points.h>
#include <CGAL/IO/write_las_points.h> #include <CGAL/IO/write_las_points.h>
#endif // LAS #endif // LAS
#include <CGAL/IO/read_ply_points.h> #include <CGAL/IO/PLY.h>
#include <CGAL/IO/write_ply_points.h>
namespace CGAL { namespace CGAL {
namespace internal namespace internal
{ {
template <typename Point, typename Vector>
class Abstract_property_printer
{
public:
virtual ~Abstract_property_printer() { }
virtual void print (std::ostream& stream, const typename CGAL::Point_set_3<Point,Vector>::Index& index) = 0;
};
template <typename Point, typename Vector, typename Type>
class Property_printer : public Abstract_property_printer<Point, Vector>
{
typedef typename CGAL::Point_set_3<Point, Vector> Point_set;
typedef typename Point_set::template Property_map<Type> Pmap;
Pmap m_pmap;
public:
Property_printer (const Pmap& pmap) : m_pmap (pmap)
{
}
virtual void print(std::ostream& stream, const typename CGAL::Point_set_3<Point,Vector>::Index& index)
{
stream << get(m_pmap, index);
}
};
template <typename Point, typename Vector, typename Type>
class Simple_property_printer : public Abstract_property_printer<Point, Vector>
{
typedef typename CGAL::Point_set_3<Point, Vector> Point_set;
typedef typename Point_set::template Property_map<Type> Pmap;
Pmap m_pmap;
public:
Simple_property_printer (const Pmap& pmap) : m_pmap (pmap)
{
}
virtual void print(std::ostream& stream, const typename CGAL::Point_set_3<Point,Vector>::Index& index)
{
if (get_mode(stream) == IO::ASCII)
stream << get(m_pmap, index);
else
{
Type t = get (m_pmap, index);
stream.write (reinterpret_cast<char*>(&t), sizeof(t));
}
}
};
template <typename Point, typename Vector, typename Type>
class Char_property_printer : public Abstract_property_printer<Point, Vector>
{
typedef typename CGAL::Point_set_3<Point, Vector> Point_set;
typedef typename Point_set::template Property_map<Type> Pmap;
Pmap m_pmap;
public:
Char_property_printer (const Pmap& pmap) : m_pmap (pmap)
{
}
virtual void print(std::ostream& stream, const typename CGAL::Point_set_3<Point,Vector>::Index& index)
{
if (get_mode(stream) == IO::ASCII)
stream << int(get(m_pmap, index));
else
{
Type t = get (m_pmap, index);
stream.write (reinterpret_cast<char*>(&t), sizeof(t));
}
}
};
namespace PLY namespace PLY
{ {
@ -365,19 +290,42 @@ read_off_point_set(
} }
/// \cond SKIP_IN_MANUAL
template <typename Point, typename Vector>
bool
read_ply_point_set(
std::istream& stream, ///< input stream.
CGAL::Point_set_3<Point, Vector>& point_set) ///< point set
{
std::string dummy;
return read_ply_point_set (stream, point_set, dummy);
}
/// \endcond
/*! /*!
\ingroup PkgPointSet3IO \ingroup PkgPointSet3IO
Reads a point set with properties from an input stream in Ascii or
Binary PLY format.
- the operator reads the vertex `point` property;
- if three PLY properties `nx`, `ny` and `nz` with type `float`
or `double` are found, the normal map is added;
- if any other PLY property is found, a "[name]" property map is
added, where `[name]` is the name of the PLY property.
The `comments` parameter can be omitted. If provided, it will be
used to store the potential comments found in the PLY
header. Each line starting by "comment " in the header is
appended to the `comments` string (without the "comment " word).
*/ */
template <typename Point, typename Vector> template <typename Point, typename Vector>
bool bool
read_ply_point_set( read_ply_point_set(
std::istream& stream, ///< input stream. std::istream& stream, ///< input stream.
#ifdef DOXYGEN_RUNNING
CGAL::Point_set_3<Point, Vector>& point_set) ///< point set
#else
CGAL::Point_set_3<Point, Vector>& point_set, ///< point set CGAL::Point_set_3<Point, Vector>& point_set, ///< point set
std::string* comments = NULL) ///< recover PLY comments std::string& comments) ///< PLY comments.
#endif
{ {
if(!stream) if(!stream)
{ {
@ -394,14 +342,14 @@ read_ply_point_set(
return false; return false;
} }
if (comments != NULL) comments = reader.comments();
*comments = reader.comments();
for (std::size_t i = 0; i < reader.number_of_elements(); ++ i) for (std::size_t i = 0; i < reader.number_of_elements(); ++ i)
{ {
internal::PLY::PLY_element& element = reader.element(i); internal::PLY::PLY_element& element = reader.element(i);
if (element.name() == "vertex" || element.name() == "vertices") bool is_vertex = (element.name() == "vertex" || element.name() == "vertices");
if (is_vertex)
{ {
point_set.reserve (element.number_of_items()); point_set.reserve (element.number_of_items());
filler.instantiate_properties (element); filler.instantiate_properties (element);
@ -417,7 +365,7 @@ read_ply_point_set(
return false; return false;
} }
if (element.name() == "vertex" || element.name() == "vertices") if (is_vertex)
filler.process_line (element); filler.process_line (element);
} }
} }
@ -427,27 +375,46 @@ read_ply_point_set(
/*! /*!
\ingroup PkgPointSet3IO \ingroup PkgPointSet3IO
Writes a point set with properties in an output stream in PLY
format.
If found, the normal map is inserted to the stream. All other
properties with simple types are inserted in the stream.
If provided, the `comments` string is included line by line in
the header of the PLY stream (each line will be precedeed by
"comment ").
*/ */
template <typename Point, typename Vector> template <typename Point, typename Vector>
bool bool
write_ply_point_set( write_ply_point_set(
std::ostream& stream, ///< output stream. std::ostream& stream, ///< output stream.
#ifdef DOXYGEN_RUNNING const CGAL::Point_set_3<Point, Vector>& point_set, ///< point set.
const CGAL::Point_set_3<Point, Vector>& point_set) ///< point set const std::string& comments = std::string()) ///< PLY comments.
#else
const CGAL::Point_set_3<Point, Vector>& point_set, ///< point set
std::string* comments = NULL) ///< write PLY comments
#endif
{ {
typedef CGAL::Point_set_3<Point, Vector> Point_set; typedef CGAL::Point_set_3<Point, Vector> Point_set;
typedef typename Point_set::Index Index;
typedef typename Point_set::Point_map Point_map;
typedef typename Point_set::Vector_map Vector_map;
typedef typename Point_set::template Property_map<boost::int8_t> Int8_map;
typedef typename Point_set::template Property_map<boost::uint8_t> Uint8_map;
typedef typename Point_set::template Property_map<boost::int16_t> Int16_map;
typedef typename Point_set::template Property_map<boost::uint16_t> Uint16_map;
typedef typename Point_set::template Property_map<boost::int32_t> Int32_map;
typedef typename Point_set::template Property_map<boost::uint32_t> Uint32_map;
typedef typename Point_set::template Property_map<boost::int64_t> Int64_map;
typedef typename Point_set::template Property_map<boost::uint64_t> Uint64_map;
typedef typename Point_set::template Property_map<float> Float_map;
typedef typename Point_set::template Property_map<double> Double_map;
stream << "ply" << std::endl stream << "ply" << std::endl
<< ((get_mode(stream) == IO::BINARY) ? "format binary_little_endian 1.0" : "format ascii 1.0") << std::endl << ((get_mode(stream) == IO::BINARY) ? "format binary_little_endian 1.0" : "format ascii 1.0") << std::endl
<< "comment Generated by the CGAL library" << std::endl; << "comment Generated by the CGAL library" << std::endl;
if (comments != NULL) if (comments != std::string())
{ {
std::istringstream iss (*comments); std::istringstream iss (comments);
std::string line; std::string line;
while (getline(iss, line)) while (getline(iss, line))
{ {
@ -459,7 +426,7 @@ write_ply_point_set(
stream << "element vertex " << point_set.number_of_points() << std::endl; stream << "element vertex " << point_set.number_of_points() << std::endl;
std::vector<std::string> prop = point_set.base().properties(); std::vector<std::string> prop = point_set.base().properties();
std::vector<internal::Abstract_property_printer<Point, Vector>*> printers; std::vector<internal::PLY::Abstract_property_printer<Index>*> printers;
for (std::size_t i = 0; i < prop.size(); ++ i) for (std::size_t i = 0; i < prop.size(); ++ i)
{ {
@ -468,7 +435,7 @@ write_ply_point_set(
if (prop[i] == "point") if (prop[i] == "point")
{ {
if (boost::is_same<typename GetFTFromMap<typename Point_set::Point_map>::type, float>::value) if (boost::is_same<typename Get_FT_from_map<typename Point_set::Point_map>::type, float>::value)
{ {
stream << "property float x" << std::endl stream << "property float x" << std::endl
<< "property float y" << std::endl << "property float y" << std::endl
@ -480,86 +447,125 @@ write_ply_point_set(
<< "property double y" << std::endl << "property double y" << std::endl
<< "property double z" << std::endl; << "property double z" << std::endl;
} }
printers.push_back (new internal::Property_printer<Point,Vector,Point>(point_set.point_map())); printers.push_back (new internal::PLY::Property_printer<Index,Point_map>(point_set.point_map()));
continue; continue;
} }
if (prop[i] == "normal") if (prop[i] == "normal")
{ {
stream << "property double nx" << std::endl if (boost::is_same<typename Get_FT_from_map<typename Point_set::Vector_map>::type, float>::value)
<< "property double ny" << std::endl {
<< "property double nz" << std::endl; stream << "property float nx" << std::endl
printers.push_back (new internal::Property_printer<Point,Vector,Vector>(point_set.normal_map())); << "property float ny" << std::endl
<< "property float nz" << std::endl;
}
else
{
stream << "property double nx" << std::endl
<< "property double ny" << std::endl
<< "property double nz" << std::endl;
}
printers.push_back (new internal::PLY::Property_printer<Index,Vector_map>(point_set.normal_map()));
continue; continue;
} }
bool okay = false; bool okay = false;
{ {
typename Point_set::template Property_map<boost::int8_t> pmap; Int8_map pmap;
boost::tie (pmap, okay) = point_set.template property_map<boost::int8_t>(prop[i]); boost::tie (pmap, okay) = point_set.template property_map<boost::int8_t>(prop[i]);
if (okay) if (okay)
{ {
stream << "property char " << prop[i] << std::endl; stream << "property char " << prop[i] << std::endl;
printers.push_back (new internal::Char_property_printer<Point,Vector,boost::int8_t>(pmap)); printers.push_back (new internal::PLY::Char_property_printer<Index,Int8_map>(pmap));
continue; continue;
} }
} }
{ {
typename Point_set::template Property_map<boost::uint8_t> pmap; Uint8_map pmap;
boost::tie (pmap, okay) = point_set.template property_map<boost::uint8_t>(prop[i]); boost::tie (pmap, okay) = point_set.template property_map<boost::uint8_t>(prop[i]);
if (okay) if (okay)
{ {
stream << "property uchar " << prop[i] << std::endl; stream << "property uchar " << prop[i] << std::endl;
printers.push_back (new internal::Char_property_printer<Point,Vector,boost::uint8_t>(pmap)); printers.push_back (new internal::PLY::Char_property_printer<Index,Uint8_map>(pmap));
continue; continue;
} }
} }
{ {
typename Point_set::template Property_map<boost::int16_t> pmap; Int16_map pmap;
boost::tie (pmap, okay) = point_set.template property_map<boost::int16_t>(prop[i]); boost::tie (pmap, okay) = point_set.template property_map<boost::int16_t>(prop[i]);
if (okay) if (okay)
{ {
stream << "property short " << prop[i] << std::endl; stream << "property short " << prop[i] << std::endl;
printers.push_back (new internal::Simple_property_printer<Point,Vector,boost::int16_t>(pmap)); printers.push_back (new internal::PLY::Simple_property_printer<Index,Int16_map>(pmap));
continue; continue;
} }
} }
{ {
typename Point_set::template Property_map<boost::uint16_t> pmap; Uint16_map pmap;
boost::tie (pmap, okay) = point_set.template property_map<boost::uint16_t>(prop[i]); boost::tie (pmap, okay) = point_set.template property_map<boost::uint16_t>(prop[i]);
if (okay) if (okay)
{ {
stream << "property ushort " << prop[i] << std::endl; stream << "property ushort " << prop[i] << std::endl;
printers.push_back (new internal::Simple_property_printer<Point,Vector,boost::uint16_t>(pmap)); printers.push_back (new internal::PLY::Simple_property_printer<Index,Uint16_map>(pmap));
continue; continue;
} }
} }
{ {
typename Point_set::template Property_map<boost::int32_t> pmap; Int32_map pmap;
boost::tie (pmap, okay) = point_set.template property_map<boost::int32_t>(prop[i]); boost::tie (pmap, okay) = point_set.template property_map<boost::int32_t>(prop[i]);
if (okay) if (okay)
{ {
stream << "property int " << prop[i] << std::endl; stream << "property int " << prop[i] << std::endl;
printers.push_back (new internal::Simple_property_printer<Point,Vector,boost::int32_t>(pmap)); printers.push_back (new internal::PLY::Simple_property_printer<Index,Int32_map>(pmap));
continue; continue;
} }
} }
{ {
typename Point_set::template Property_map<float> pmap; Uint32_map pmap;
boost::tie (pmap, okay) = point_set.template property_map<boost::uint32_t>(prop[i]);
if (okay)
{
stream << "property uint " << prop[i] << std::endl;
printers.push_back (new internal::PLY::Simple_property_printer<Index,Uint32_map>(pmap));
continue;
}
}
{
Int64_map pmap;
boost::tie (pmap, okay) = point_set.template property_map<boost::int64_t>(prop[i]);
if (okay)
{
stream << "property int " << prop[i] << std::endl;
printers.push_back (new internal::PLY::Simple_property_printer<Index,Int64_map,boost::int32_t>(pmap));
continue;
}
}
{
Uint64_map pmap;
boost::tie (pmap, okay) = point_set.template property_map<boost::uint64_t>(prop[i]);
if (okay)
{
stream << "property uint " << prop[i] << std::endl;
printers.push_back (new internal::PLY::Simple_property_printer<Index,Uint64_map,boost::uint32_t>(pmap));
continue;
}
}
{
Float_map pmap;
boost::tie (pmap, okay) = point_set.template property_map<float>(prop[i]); boost::tie (pmap, okay) = point_set.template property_map<float>(prop[i]);
if (okay) if (okay)
{ {
stream << "property float " << prop[i] << std::endl; stream << "property float " << prop[i] << std::endl;
printers.push_back (new internal::Simple_property_printer<Point,Vector,float>(pmap)); printers.push_back (new internal::PLY::Simple_property_printer<Index,Float_map>(pmap));
continue; continue;
} }
} }
{ {
typename Point_set::template Property_map<double> pmap; Double_map pmap;
boost::tie (pmap, okay) = point_set.template property_map<double>(prop[i]); boost::tie (pmap, okay) = point_set.template property_map<double>(prop[i]);
if (okay) if (okay)
{ {
stream << "property double " << prop[i] << std::endl; stream << "property double " << prop[i] << std::endl;
printers.push_back (new internal::Simple_property_printer<Point,Vector,double>(pmap)); printers.push_back (new internal::PLY::Simple_property_printer<Index,Double_map>(pmap));
continue; continue;
} }
} }

View File

@ -27,6 +27,7 @@
#include <tuple> #include <tuple>
#include <CGAL/IO/PLY.h>
#include <CGAL/property_map.h> #include <CGAL/property_map.h>
#include <CGAL/value_type_traits.h> #include <CGAL/value_type_traits.h>
#include <CGAL/point_set_processing_assertions.h> #include <CGAL/point_set_processing_assertions.h>
@ -43,36 +44,9 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
#define TRY_TO_GENERATE_PROPERTY(STD_TYPE, T_TYPE, TYPE) \
if (type == STD_TYPE || type == T_TYPE) \
m_elements.back().add_property (new PLY_read_typed_number< TYPE > (name, format))
#define TRY_TO_GENERATE_SIZED_LIST_PROPERTY(STD_SIZE_TYPE, T_SIZE_TYPE, SIZE_TYPE, STD_INDEX_TYPE, T_INDEX_TYPE, INDEX_TYPE) \
if ((size_type == STD_SIZE_TYPE || size_type == T_SIZE_TYPE) && \
(index_type == STD_INDEX_TYPE || index_type == T_INDEX_TYPE)) \
m_elements.back().add_property (new PLY_read_typed_list_with_typed_size< SIZE_TYPE , INDEX_TYPE > (name, format))
#define TRY_TO_GENERATE_LIST_PROPERTY(STD_INDEX_TYPE, T_INDEX_TYPE, INDEX_TYPE) \
TRY_TO_GENERATE_SIZED_LIST_PROPERTY("uchar", "uint8", boost::uint8_t, STD_INDEX_TYPE, T_INDEX_TYPE, INDEX_TYPE); \
else TRY_TO_GENERATE_SIZED_LIST_PROPERTY("ushort", "uint16", boost::uint16_t, STD_INDEX_TYPE, T_INDEX_TYPE, INDEX_TYPE); \
else TRY_TO_GENERATE_SIZED_LIST_PROPERTY("uint", "uint32", boost::uint32_t, STD_INDEX_TYPE, T_INDEX_TYPE, INDEX_TYPE)
namespace CGAL { namespace CGAL {
#ifdef DOXYGEN_RUNNING // Document some parts from Stream_support here for convenience
// PLY types:
// name type number of bytes
// ---------------------------------------
// char character 1
// uchar unsigned character 1
// short short integer 2
// ushort unsigned short integer 2
// int integer 4
// uint unsigned integer 4
// float single-precision float 4
// double double-precision float 8
/** /**
\ingroup PkgPointSetProcessing3IOPly \ingroup PkgPointSetProcessing3IOPly
@ -88,23 +62,6 @@ namespace CGAL {
PLY_property (const char* name) : name (name) { } PLY_property (const char* name) : name (name) { }
}; };
/// \cond SKIP_IN_MANUAL
// Use a double property for all kernels...
template <typename FT> struct Convert_FT { typedef double type; };
// ...except if kernel uses type float
template <> struct Convert_FT<float> { typedef float type; };
template <typename PointOrVectorMap>
struct GetFTFromMap
{
typedef typename Convert_FT
<typename Kernel_traits
<typename boost::property_traits
<PointOrVectorMap>::value_type>::Kernel::FT>::type type;
};
/// \endcond
/** /**
\ingroup PkgPointSetProcessing3IOPly \ingroup PkgPointSetProcessing3IOPly
@ -118,24 +75,10 @@ namespace CGAL {
\tparam PointMap the property map used to store points. \tparam PointMap the property map used to store points.
*/ */
template <typename PointMap> template <typename PointMap>
#ifdef DOXYGEN_RUNNING
std::tuple<PointMap, std::tuple<PointMap,
typename Kernel_traits<typename PointMap::value_type>::Kernel::Construct_point_3, typename Kernel_traits<typename PointMap::value_type>::Kernel::Construct_point_3,
PLY_property<FT>, PLY_property<FT>, PLY_property<FT> > PLY_property<FT>, PLY_property<FT>, PLY_property<FT> >
#else make_ply_point_reader(PointMap point_map);
std::tuple<PointMap,
typename Kernel_traits<typename PointMap::value_type>::Kernel::Construct_point_3,
PLY_property<typename GetFTFromMap<PointMap>::type>,
PLY_property<typename GetFTFromMap<PointMap>::type>,
PLY_property<typename GetFTFromMap<PointMap>::type> >
#endif
make_ply_point_reader(PointMap point_map)
{
return std::make_tuple (point_map, typename Kernel_traits<typename PointMap::value_type>::Kernel::Construct_point_3(),
PLY_property<typename GetFTFromMap<PointMap>::type>("x"),
PLY_property<typename GetFTFromMap<PointMap>::type>("y"),
PLY_property<typename GetFTFromMap<PointMap>::type>("z"));
}
/** /**
\ingroup PkgPointSetProcessing3IOPly \ingroup PkgPointSetProcessing3IOPly
@ -151,573 +94,11 @@ namespace CGAL {
\tparam VectorMap the property map used to store vectors. \tparam VectorMap the property map used to store vectors.
*/ */
template <typename VectorMap> template <typename VectorMap>
#ifdef DOXYGEN_RUNNING
std::tuple<VectorMap, std::tuple<VectorMap,
typename Kernel_traits<typename VectorMap::value_type>::Kernel::Construct_vector_3, typename Kernel_traits<typename VectorMap::value_type>::Kernel::Construct_vector_3,
PLY_property<FT>, PLY_property<FT>, PLY_property<FT> > PLY_property<FT>, PLY_property<FT>, PLY_property<FT> >
#else make_ply_normal_reader(VectorMap normal_map);
std::tuple<VectorMap, #endif // DOXYGEN_RUNNING
typename Kernel_traits<typename VectorMap::value_type>::Kernel::Construct_vector_3,
PLY_property<typename GetFTFromMap<VectorMap>::type>,
PLY_property<typename GetFTFromMap<VectorMap>::type>,
PLY_property<typename GetFTFromMap<VectorMap>::type> >
#endif
make_ply_normal_reader(VectorMap normal_map)
{
return std::make_tuple (normal_map, typename Kernel_traits<typename VectorMap::value_type>::Kernel::Construct_vector_3(),
PLY_property<typename GetFTFromMap<VectorMap>::type>("nx"),
PLY_property<typename GetFTFromMap<VectorMap>::type>("ny"),
PLY_property<typename GetFTFromMap<VectorMap>::type>("nz"));
}
/// \cond SKIP_IN_MANUAL
namespace internal {
namespace PLY {
class PLY_read_number
{
protected:
std::string m_name;
std::size_t m_format;
public:
PLY_read_number (std::string name, std::size_t format)
: m_name (name), m_format (format) { }
virtual ~PLY_read_number() { }
const std::string& name () const { return m_name; }
virtual void get (std::istream& stream) const = 0;
// The two following functions prevent the stream to only extract
// ONE character (= what the types char imply) by requiring
// explicitely an integer object when reading the stream
void read_ascii (std::istream& stream, char& c) const
{
short s;
stream >> s;
c = static_cast<char>(s);
}
void read_ascii (std::istream& stream, signed char& c) const
{
short s;
stream >> s;
c = static_cast<signed char>(s);
}
void read_ascii (std::istream& stream, unsigned char& c) const
{
unsigned short s;
stream >> s;
c = static_cast<unsigned char>(s);
}
void read_ascii (std::istream& stream, float& t) const
{
stream >> iformat(t);
}
void read_ascii (std::istream& stream, double& t) const
{
stream >> iformat(t);
}
// Default template when Type is not a char type
template <typename Type>
void read_ascii (std::istream& stream, Type& t) const
{
stream >> t;
}
template <typename Type>
Type read (std::istream& stream) const
{
if (m_format == 0) // Ascii
{
Type t;
read_ascii (stream, t);
return t;
}
else // Binary (2 = little endian)
{
union
{
char uChar[sizeof (Type)];
Type type;
} buffer;
std::size_t size = sizeof (Type);
stream.read(buffer.uChar, size);
if (m_format == 2) // Big endian
{
for (std::size_t i = 0; i < size / 2; ++ i)
{
unsigned char tmp = buffer.uChar[i];
buffer.uChar[i] = buffer.uChar[size - 1 - i];
buffer.uChar[size - 1 - i] = tmp;
}
}
return buffer.type;
}
return Type();
}
};
template <typename Type>
class PLY_read_typed_number : public PLY_read_number
{
mutable Type m_buffer;
public:
PLY_read_typed_number (std::string name, std::size_t format)
: PLY_read_number (name, format)
{
}
void get (std::istream& stream) const
{
m_buffer = (this->read<Type> (stream));
}
const Type& buffer() const
{
return m_buffer;
}
};
template <typename Type>
class PLY_read_typed_list : public PLY_read_number
{
protected:
mutable std::vector<Type> m_buffer;
public:
PLY_read_typed_list (std::string name, std::size_t format)
: PLY_read_number (name, format)
{
}
virtual void get (std::istream& stream) const = 0;
const std::vector<Type>& buffer() const
{
return m_buffer;
}
};
template <typename SizeType, typename IndexType>
class PLY_read_typed_list_with_typed_size
: public PLY_read_typed_list<IndexType>
{
public:
PLY_read_typed_list_with_typed_size (std::string name, std::size_t format)
: PLY_read_typed_list<IndexType> (name, format)
{
}
void get (std::istream& stream) const
{
std::size_t size = static_cast<std::size_t>(this->template read<SizeType>(stream));
this->m_buffer.resize (size);
for (std::size_t i = 0; i < size; ++ i)
this->m_buffer[i] = this->template read<IndexType> (stream);
}
};
class PLY_element
{
std::string m_name;
std::size_t m_number;
std::vector<PLY_read_number*> m_properties;
public:
PLY_element (const std::string& name, std::size_t number)
: m_name (name), m_number (number)
{ }
PLY_element (const PLY_element& other)
: m_name (other.m_name), m_number (other.m_number), m_properties (other.m_properties)
{
const_cast<PLY_element&>(other).m_properties.clear();
}
PLY_element& operator= (const PLY_element& other)
{
m_name = other.m_name;
m_number = other.m_number;
m_properties = other.m_properties;
const_cast<PLY_element&>(other).m_properties.clear();
return *this;
}
~PLY_element()
{
for (std::size_t i = 0; i < m_properties.size(); ++ i)
delete m_properties[i];
}
const std::string& name() const { return m_name; }
std::size_t number_of_items() const { return m_number; }
std::size_t number_of_properties() const { return m_properties.size(); }
PLY_read_number* property (std::size_t idx) { return m_properties[idx]; }
void add_property (PLY_read_number* read_number)
{
m_properties.push_back (read_number);
}
template <typename Type>
bool has_property (const char* tag)
{
return has_property (tag, Type());
}
template <typename Type>
bool has_property (const char* tag, const std::vector<Type>&)
{
for (std::size_t i = 0; i < number_of_properties(); ++ i)
if (m_properties[i]->name () == tag)
return (dynamic_cast<PLY_read_typed_list<Type>*>(m_properties[i]) != NULL);
return false;
}
template <typename Type>
bool has_property (const char* tag, Type)
{
for (std::size_t i = 0; i < number_of_properties(); ++ i)
if (m_properties[i]->name () == tag)
return (dynamic_cast<PLY_read_typed_number<Type>*>(m_properties[i]) != NULL);
return false;
}
bool has_property (const char* tag, double)
{
for (std::size_t i = 0; i < number_of_properties(); ++ i)
if (m_properties[i]->name () == tag)
return (dynamic_cast<PLY_read_typed_number<double>*>(m_properties[i]) != NULL
|| dynamic_cast<PLY_read_typed_number<float>*>(m_properties[i]) != NULL);
return false;
}
template <typename Type>
void assign (Type& t, const char* tag)
{
for (std::size_t i = 0; i < number_of_properties (); ++ i)
if (m_properties[i]->name () == tag)
{
PLY_read_typed_number<Type>*
property = dynamic_cast<PLY_read_typed_number<Type>*>(m_properties[i]);
CGAL_assertion (property != NULL);
t = property->buffer();
return;
}
}
template <typename Type>
void assign (std::vector<Type>& t, const char* tag)
{
for (std::size_t i = 0; i < number_of_properties (); ++ i)
if (m_properties[i]->name () == tag)
{
PLY_read_typed_list<Type>*
property = dynamic_cast<PLY_read_typed_list<Type>*>(m_properties[i]);
CGAL_assertion (property != NULL);
t = property->buffer();
return;
}
}
void assign (double& t, const char* tag)
{
for (std::size_t i = 0; i < number_of_properties (); ++ i)
if (m_properties[i]->name () == tag)
{
PLY_read_typed_number<double>*
property_double = dynamic_cast<PLY_read_typed_number<double>*>(m_properties[i]);
if (property_double == NULL)
{
PLY_read_typed_number<float>*
property_float = dynamic_cast<PLY_read_typed_number<float>*>(m_properties[i]);
CGAL_assertion (property_float != NULL);
t = property_float->buffer();
}
else
t = property_double->buffer();
return;
}
}
};
class PLY_reader
{
std::vector<PLY_element> m_elements;
std::string m_comments;
public:
PLY_reader () { }
std::size_t number_of_elements() const { return m_elements.size(); }
PLY_element& element (std::size_t idx)
{
return m_elements[idx];
}
const std::string& comments() const { return m_comments; }
template <typename Stream>
bool init (Stream& stream)
{
std::size_t lineNumber = 0; // current line number
enum Format { ASCII = 0, BINARY_LITTLE_ENDIAN = 1, BINARY_BIG_ENDIAN = 2};
Format format = ASCII;
std::string line;
std::istringstream iss;
while (getline (stream,line))
{
iss.clear();
iss.str (line);
++ lineNumber;
// Reads file signature on first line
if (lineNumber == 1)
{
std::string signature;
if (!(iss >> signature) || (signature != "ply"))
{
// if wrong file format
std::cerr << "Error: incorrect file format line " << lineNumber << " of file" << std::endl;
return false;
}
}
// Reads format on 2nd line
else if (lineNumber == 2)
{
std::string tag, format_string, version;
if ( !(iss >> tag >> format_string >> version) )
{
std::cerr << "Error line " << lineNumber << " of file" << std::endl;
return false;
}
if (format_string == "ascii") format = ASCII;
else if (format_string == "binary_little_endian") format = BINARY_LITTLE_ENDIAN;
else if (format_string == "binary_big_endian") format = BINARY_BIG_ENDIAN;
else
{
std::cerr << "Error: unknown file format \"" << format_string << "\" line " << lineNumber << std::endl;
return false;
}
}
// Comments and vertex properties
else
{
std::string keyword;
if (!(iss >> keyword))
{
std::cerr << "Error line " << lineNumber << " of file" << std::endl;
return false;
}
if (keyword == "property")
{
std::string type, name;
if (!(iss >> type >> name))
{
std::cerr << "Error line " << lineNumber << " of file" << std::endl;
return false;
}
if (type == "list") // Special case
{
std::string size_type = name;
std::string index_type;
name.clear();
if (!(iss >> index_type >> name))
{
std::cerr << "Error line " << lineNumber << " of file" << std::endl;
return false;
}
TRY_TO_GENERATE_LIST_PROPERTY ("char", "int8", boost::int8_t);
else TRY_TO_GENERATE_LIST_PROPERTY ("uchar", "uint8", boost::uint8_t);
else TRY_TO_GENERATE_LIST_PROPERTY ("short", "int16", boost::int16_t);
else TRY_TO_GENERATE_LIST_PROPERTY ("ushort", "uint16", boost::uint16_t);
else TRY_TO_GENERATE_LIST_PROPERTY ("int", "int32", boost::int32_t);
else TRY_TO_GENERATE_LIST_PROPERTY ("uint", "uint32", boost::uint32_t);
else TRY_TO_GENERATE_LIST_PROPERTY ("float", "float32", float);
else TRY_TO_GENERATE_LIST_PROPERTY ("double", "float64", double);
}
else
{
TRY_TO_GENERATE_PROPERTY ("char", "int8", boost::int8_t);
else TRY_TO_GENERATE_PROPERTY ("uchar", "uint8", boost::uint8_t);
else TRY_TO_GENERATE_PROPERTY ("short", "int16", boost::int16_t);
else TRY_TO_GENERATE_PROPERTY ("ushort", "uint16", boost::uint16_t);
else TRY_TO_GENERATE_PROPERTY ("int", "int32", boost::int32_t);
else TRY_TO_GENERATE_PROPERTY ("uint", "uint32", boost::uint32_t);
else TRY_TO_GENERATE_PROPERTY ("float", "float32", float);
else TRY_TO_GENERATE_PROPERTY ("double", "float64", double);
}
continue;
}
else if (keyword == "comment")
{
std::string str = iss.str();
if (str.size() > 8)
{
std::copy (str.begin() + 8, str.end(), std::back_inserter (m_comments));
m_comments += "\n";
}
}
else if (keyword == "element")
{
std::string type;
std::size_t number;
if (!(iss >> type >> number))
{
std::cerr << "Error line " << lineNumber << " of file" << std::endl;
return false;
}
m_elements.push_back (PLY_element(type, number));
}
// When end_header is reached, stop loop and begin reading points
else if (keyword == "end_header")
break;
}
}
return true;
}
~PLY_reader ()
{
}
};
template <class Reader, class T>
void get_value(Reader& r, T& v, PLY_property<T>& wrapper)
{
return r.assign(v, wrapper.name);
}
template <std::size_t N>
struct Filler
{
template <class Reader, class Value_tuple, class PLY_property_tuple>
static void fill(Reader& r, Value_tuple& values, PLY_property_tuple wrappers)
{
get_value(r, std::get<N>(values), std::get<N+2>(wrappers));
Filler<N-1>::fill(r, values, wrappers);
}
};
template<int ...>
struct seq { };
template<int N, int ...S>
struct gens : gens<N-1, N-1, S...> { };
template<int ...S>
struct gens<0, S...> {
typedef seq<S...> type;
};
template<class ValueType, class Functor, class Tuple, int ...S>
ValueType call_functor(Functor f, Tuple t, seq<S...>) {
return f(std::get<S>(t) ...);
}
template <class ValueType, class Functor, typename ... T>
ValueType call_functor(Functor f, std::tuple<T...>& t)
{
return call_functor<ValueType>(f, t, typename gens<sizeof...(T)>::type());
}
template<>
struct Filler<0>
{
template <class Reader, class Value_tuple, class PLY_property_tuple>
static void fill(Reader& r, Value_tuple& values, PLY_property_tuple wrappers)
{
get_value(r, std::get<0>(values), std::get<2>(wrappers));
}
};
template <typename OutputValueType,
typename PropertyMap,
typename Constructor,
typename ... T>
void process_properties (PLY_element& element, OutputValueType& new_element,
std::tuple<PropertyMap, Constructor, PLY_property<T>...>&& current)
{
typedef typename PropertyMap::value_type PmapValueType;
std::tuple<T...> values;
Filler<sizeof...(T)-1>::fill(element, values, current);
PmapValueType new_value = call_functor<PmapValueType>(std::get<1>(current), values);
put (std::get<0>(current), new_element, new_value);
}
template <typename OutputValueType,
typename PropertyMap,
typename Constructor,
typename ... T,
typename NextPropertyBinder,
typename ... PropertyMapBinders>
void process_properties (PLY_element& element, OutputValueType& new_element,
std::tuple<PropertyMap, Constructor, PLY_property<T>...>&& current,
NextPropertyBinder&& next,
PropertyMapBinders&& ... properties)
{
typedef typename PropertyMap::value_type PmapValueType;
std::tuple<T...> values;
Filler<sizeof...(T)-1>::fill(element, values, current);
PmapValueType new_value = call_functor<PmapValueType>(std::get<1>(current), values);
put (std::get<0>(current), new_element, new_value);
process_properties (element, new_element, std::forward<NextPropertyBinder>(next),
std::forward<PropertyMapBinders>(properties)...);
}
template <typename OutputValueType, typename PropertyMap, typename T>
void process_properties (PLY_element& element, OutputValueType& new_element,
std::pair<PropertyMap, PLY_property<T> >&& current)
{
T new_value = T();
element.assign (new_value, current.second.name);
put (current.first, new_element, new_value);
}
template <typename OutputValueType, typename PropertyMap, typename T,
typename NextPropertyBinder, typename ... PropertyMapBinders>
void process_properties (PLY_element& element, OutputValueType& new_element,
std::pair<PropertyMap, PLY_property<T> >&& current,
NextPropertyBinder&& next,
PropertyMapBinders&& ... properties)
{
T new_value = T();
element.assign (new_value, current.second.name);
put (current.first, new_element, new_value);
process_properties (element, new_element, std::forward<NextPropertyBinder>(next),
std::forward<PropertyMapBinders>(properties)...);
}
} // namespace PLY
} // namespace internal
/// \endcond
/* /*
\ingroup PkgPointSetProcessing3IOPly \ingroup PkgPointSetProcessing3IOPly

View File

@ -27,9 +27,9 @@
#include <tuple> #include <tuple>
#include <CGAL/IO/PLY.h>
#include <CGAL/property_map.h> #include <CGAL/property_map.h>
#include <CGAL/point_set_processing_assertions.h> #include <CGAL/point_set_processing_assertions.h>
#include <CGAL/IO/read_ply_points.h>
#include <CGAL/Iterator_range.h> #include <CGAL/Iterator_range.h>
#include <CGAL/boost/graph/named_function_params.h> #include <CGAL/boost/graph/named_function_params.h>
@ -42,6 +42,7 @@
namespace CGAL { namespace CGAL {
#ifdef DOXYGEN_RUNNING // Document some parts from Stream_support here for convenience
/** /**
\ingroup PkgPointSetProcessing3IOPly \ingroup PkgPointSetProcessing3IOPly
@ -55,21 +56,8 @@ namespace CGAL {
\tparam PointMap the property map used to store points. \tparam PointMap the property map used to store points.
*/ */
template <typename PointMap> template <typename PointMap>
#ifdef DOXYGEN_RUNNING
std::tuple<PointMap, PLY_property<FT>, PLY_property<FT>, PLY_property<FT> > std::tuple<PointMap, PLY_property<FT>, PLY_property<FT>, PLY_property<FT> >
#else make_ply_point_writer(PointMap point_map);
std::tuple<PointMap,
PLY_property<typename GetFTFromMap<PointMap>::type>,
PLY_property<typename GetFTFromMap<PointMap>::type>,
PLY_property<typename GetFTFromMap<PointMap>::type> >
#endif
make_ply_point_writer(PointMap point_map)
{
return std::make_tuple (point_map,
PLY_property<typename GetFTFromMap<PointMap>::type>("x"),
PLY_property<typename GetFTFromMap<PointMap>::type>("y"),
PLY_property<typename GetFTFromMap<PointMap>::type>("z"));
}
/** /**
\ingroup PkgPointSetProcessing3IOPly \ingroup PkgPointSetProcessing3IOPly
@ -84,21 +72,9 @@ namespace CGAL {
\tparam VectorMap the property map used to store vectors. \tparam VectorMap the property map used to store vectors.
*/ */
template <typename VectorMap> template <typename VectorMap>
#ifdef DOXYGEN_RUNNING
std::tuple<VectorMap, PLY_property<FT>, PLY_property<FT>, PLY_property<FT> > std::tuple<VectorMap, PLY_property<FT>, PLY_property<FT>, PLY_property<FT> >
#else make_ply_normal_writer(VectorMap normal_map);
std::tuple<VectorMap,
PLY_property<typename GetFTFromMap<VectorMap>::type>,
PLY_property<typename GetFTFromMap<VectorMap>::type>,
PLY_property<typename GetFTFromMap<VectorMap>::type> >
#endif #endif
make_ply_normal_writer(VectorMap normal_map)
{
return std::make_tuple (normal_map,
PLY_property<typename GetFTFromMap<VectorMap>::type>("nx"),
PLY_property<typename GetFTFromMap<VectorMap>::type>("ny"),
PLY_property<typename GetFTFromMap<VectorMap>::type>("nz"));
}
/// \cond SKIP_IN_MANUAL /// \cond SKIP_IN_MANUAL
@ -106,219 +82,6 @@ namespace internal {
namespace PLY { namespace PLY {
template <typename T> void property_header_type (std::ostream& stream)
{
CGAL_assertion_msg (false, "Unknown PLY type");
stream << "undefined_type";
}
template <> void property_header_type<char> (std::ostream& stream) { stream << "char"; }
template <> void property_header_type<signed char> (std::ostream& stream) { stream << "char"; }
template <> void property_header_type<unsigned char> (std::ostream& stream) { stream << "uchar"; }
template <> void property_header_type<short> (std::ostream& stream) { stream << "short"; }
template <> void property_header_type<unsigned short> (std::ostream& stream) { stream << "ushort"; }
template <> void property_header_type<int> (std::ostream& stream) { stream << "int"; }
template <> void property_header_type<unsigned int> (std::ostream& stream) { stream << "uint"; }
template <> void property_header_type<float> (std::ostream& stream) { stream << "float"; }
template <> void property_header_type<double> (std::ostream& stream) { stream << "double"; }
template <typename T>
void property_header (std::ostream& stream, const PLY_property<T>& prop)
{
stream << "property ";
property_header_type<T>(stream);
stream << " " << prop.name << std::endl;
}
template <typename T>
void property_header (std::ostream& stream, const PLY_property<std::vector<T> >& prop)
{
stream << "property list uchar ";
property_header_type<T>(stream);
stream << " " << prop.name << std::endl;
}
template <std::size_t N>
struct Properties_header
{
template <class PLY_property_tuple>
static void write(std::ostream& stream, PLY_property_tuple& wrappers)
{
Properties_header<N-1>::write(stream, wrappers);
property_header (stream, std::get<N+1>(wrappers));
}
};
template <>
struct Properties_header<0>
{
template <class PLY_property_tuple>
static void write(std::ostream& stream, PLY_property_tuple& wrappers)
{
property_header (stream, std::get<1>(wrappers));
}
};
template <typename PropertyMap,
typename ... T>
void output_property_header (std::ostream& stream,
std::tuple<PropertyMap, PLY_property<T>... >&& current)
{
Properties_header<sizeof...(T)-1>::write(stream, current);
}
template <typename PropertyMap,
typename T>
void output_property_header (std::ostream& stream,
std::pair<PropertyMap, PLY_property<T> >&& current)
{
property_header (stream, current.second);
}
template <typename PropertyMap,
typename T,
typename NextPropertyHandler,
typename ... PropertyHandler>
void output_property_header (std::ostream& stream,
std::pair<PropertyMap, PLY_property<T> >&& current,
NextPropertyHandler&& next,
PropertyHandler&& ... properties)
{
property_header (stream, current.second);
output_property_header (stream, std::forward<NextPropertyHandler>(next),
std::forward<PropertyHandler>(properties)...);
}
template <typename PropertyMap,
typename ... T,
typename NextPropertyHandler,
typename ... PropertyHandler>
void output_property_header (std::ostream& stream,
std::tuple<PropertyMap, PLY_property<T>... >&& current,
NextPropertyHandler&& next,
PropertyHandler&& ... properties)
{
Properties_header<sizeof...(T)-1>::write(stream, current);
output_property_header (stream, std::forward<NextPropertyHandler>(next),
std::forward<PropertyHandler>(properties)...);
}
template <typename ForwardIterator,
typename PropertyMap>
void property_write (std::ostream& stream, ForwardIterator it, PropertyMap map)
{
stream << CGAL::oformat(get (map, *it));
}
template <typename T>
T no_char_character (const T& t) { return t; }
int no_char_character (const char& t) { return int(t); }
int no_char_character (const signed char& t) { return int(t); }
int no_char_character (const unsigned char& t) { return int(t); }
template <typename ForwardIterator,
typename PropertyMap,
typename T>
void simple_property_write (std::ostream& stream, ForwardIterator it,
std::pair<PropertyMap, PLY_property<T> > map)
{
if (CGAL::get_mode(stream) == IO::ASCII)
stream << no_char_character(get (map.first, *it));
else
{
typename PropertyMap::value_type value = get(map.first, *it);
stream.write (reinterpret_cast<char*>(&value), sizeof(value));
}
}
template <typename ForwardIterator,
typename PropertyMap,
typename T>
void simple_property_write (std::ostream& stream, ForwardIterator it,
std::pair<PropertyMap, PLY_property<std::vector<T> > > map)
{
const typename PropertyMap::reference value = get(map.first, *it);
if (CGAL::get_mode(stream) == IO::ASCII)
{
stream << value.size();
for (std::size_t i = 0; i < value.size(); ++ i)
stream << " " << no_char_character(value[i]);
}
else
{
unsigned char size = static_cast<unsigned char>(value.size());
stream.write (reinterpret_cast<char*>(&size), sizeof(size));
for (std::size_t i = 0; i < value.size(); ++ i)
{
T t = T(value[i]);
stream.write (reinterpret_cast<char*>(&t), sizeof(t));
}
}
}
template <typename ForwardIterator,
typename PropertyMap,
typename ... T>
void output_properties (std::ostream& stream,
ForwardIterator it,
std::tuple<PropertyMap, PLY_property<T>... >&& current)
{
property_write (stream, it, std::get<0>(current));
if (get_mode(stream) == IO::ASCII)
stream << std::endl;
}
template <typename ForwardIterator,
typename PropertyMap,
typename T>
void output_properties (std::ostream& stream,
ForwardIterator it,
std::pair<PropertyMap, PLY_property<T> >&& current)
{
simple_property_write (stream, it, std::forward<std::pair<PropertyMap, PLY_property<T> > >(current));
if (get_mode(stream) == IO::ASCII)
stream << std::endl;
}
template <typename ForwardIterator,
typename PropertyMap,
typename T,
typename NextPropertyHandler,
typename ... PropertyHandler>
void output_properties (std::ostream& stream,
ForwardIterator it,
std::pair<PropertyMap, PLY_property<T> >&& current,
NextPropertyHandler&& next,
PropertyHandler&& ... properties)
{
simple_property_write (stream, it, current);
if (get_mode(stream) == IO::ASCII)
stream << " ";
output_properties (stream, it, std::forward<NextPropertyHandler>(next),
std::forward<PropertyHandler>(properties)...);
}
template <typename ForwardIterator,
typename PropertyMap,
typename ... T,
typename NextPropertyHandler,
typename ... PropertyHandler>
void output_properties (std::ostream& stream,
ForwardIterator it,
std::tuple<PropertyMap, PLY_property<T>... >&& current,
NextPropertyHandler&& next,
PropertyHandler&& ... properties)
{
property_write (stream, it, std::get<0>(current));
if (get_mode(stream) == IO::ASCII)
stream << " ";
output_properties (stream, it, std::forward<NextPropertyHandler>(next),
std::forward<PropertyHandler>(properties)...);
}
} // namespace PLY } // namespace PLY

View File

@ -396,12 +396,12 @@ void Cluster_classification::backup_existing_colors_and_add_new()
{ {
if (m_points->point_set()->has_colors()) if (m_points->point_set()->has_colors())
{ {
m_color = m_points->point_set()->add_property_map<Color>("real_color").first; m_color = m_points->point_set()->add_property_map<CGAL::Color>("real_color").first;
for (Point_set::const_iterator it = m_points->point_set()->begin(); for (Point_set::const_iterator it = m_points->point_set()->begin();
it != m_points->point_set()->first_selected(); ++ it) it != m_points->point_set()->first_selected(); ++ it)
m_color[*it] = {{ (unsigned char)(255 * m_points->point_set()->red(*it)), m_color[*it] = CGAL::Color ((unsigned char)(255 * m_points->point_set()->red(*it)),
(unsigned char)(255 * m_points->point_set()->green(*it)), (unsigned char)(255 * m_points->point_set()->green(*it)),
(unsigned char)(255 * m_points->point_set()->blue(*it)) }}; (unsigned char)(255 * m_points->point_set()->blue(*it)));
m_points->point_set()->remove_colors(); m_points->point_set()->remove_colors();
} }
@ -411,7 +411,7 @@ void Cluster_classification::backup_existing_colors_and_add_new()
void Cluster_classification::reset_colors() void Cluster_classification::reset_colors()
{ {
if (m_color == Point_set::Property_map<Color>()) if (m_color == Point_set::Property_map<CGAL::Color>())
m_points->point_set()->remove_colors(); m_points->point_set()->remove_colors();
else else
{ {
@ -606,7 +606,7 @@ int Cluster_classification::real_index_color() const
{ {
int out = m_index_color; int out = m_index_color;
if (out == 0 && m_color == Point_set::Property_map<Color>()) if (out == 0 && m_color == Point_set::Property_map<CGAL::Color>())
out = -1; out = -1;
return out; return out;
} }
@ -642,7 +642,7 @@ void Cluster_classification::compute_features (std::size_t nb_scales, float voxe
if (normals) if (normals)
normal_map = m_points->point_set()->normal_map(); normal_map = m_points->point_set()->normal_map();
bool colors = (m_color != Point_set::Property_map<Color>()); bool colors = (m_color != Point_set::Property_map<CGAL::Color>());
Point_set::Property_map<boost::uint8_t> echo_map; Point_set::Property_map<boost::uint8_t> echo_map;
bool echo; bool echo;

View File

@ -27,7 +27,6 @@ class Cluster_classification : public Item_classification_base
public: public:
typedef Kernel::Point_3 Point_3; typedef Kernel::Point_3 Point_3;
typedef Kernel::Vector_3 Vector_3; typedef Kernel::Vector_3 Vector_3;
typedef CGAL::Classification::RGB_Color Color;
typedef Point_set::Point_map Point_map; typedef Point_set::Point_map Point_map;
typedef Point_set::Vector_map Vector_map; typedef Point_set::Vector_map Vector_map;
@ -382,7 +381,10 @@ class Cluster_classification : public Item_classification_base
std::vector<Cluster> m_clusters; std::vector<Cluster> m_clusters;
Point_set::Property_map<Color> m_color; Point_set::Property_map<unsigned char> m_red;
Point_set::Property_map<unsigned char> m_green;
Point_set::Property_map<unsigned char> m_blue;
Point_set::Property_map<CGAL::Color> m_color;
Point_set::Property_map<int> m_cluster_id; Point_set::Property_map<int> m_cluster_id;
Point_set::Property_map<int> m_training; Point_set::Property_map<int> m_training;
Point_set::Property_map<int> m_classif; Point_set::Property_map<int> m_classif;

View File

@ -327,12 +327,12 @@ void Point_set_item_classification::backup_existing_colors_and_add_new()
{ {
if (m_points->point_set()->has_colors()) if (m_points->point_set()->has_colors())
{ {
m_color = m_points->point_set()->add_property_map<Color>("real_color").first; m_color = m_points->point_set()->add_property_map<CGAL::Color>("real_color").first;
for (Point_set::const_iterator it = m_points->point_set()->begin(); for (Point_set::const_iterator it = m_points->point_set()->begin();
it != m_points->point_set()->first_selected(); ++ it) it != m_points->point_set()->first_selected(); ++ it)
m_color[*it] = {{ (unsigned char)(255 * m_points->point_set()->red(*it)), m_color[*it] = CGAL::Color((unsigned char)(255 * m_points->point_set()->red(*it)),
(unsigned char)(255 * m_points->point_set()->green(*it)), (unsigned char)(255 * m_points->point_set()->green(*it)),
(unsigned char)(255 * m_points->point_set()->blue(*it)) }}; (unsigned char)(255 * m_points->point_set()->blue(*it)));
m_points->point_set()->remove_colors(); m_points->point_set()->remove_colors();
} }
@ -342,7 +342,7 @@ void Point_set_item_classification::backup_existing_colors_and_add_new()
void Point_set_item_classification::reset_colors() void Point_set_item_classification::reset_colors()
{ {
if (m_color == Point_set::Property_map<Color>()) if (m_color == Point_set::Property_map<CGAL::Color>())
m_points->point_set()->remove_colors(); m_points->point_set()->remove_colors();
else else
{ {
@ -493,7 +493,7 @@ int Point_set_item_classification::real_index_color() const
{ {
int out = m_index_color; int out = m_index_color;
if (out == 0 && m_color == Point_set::Property_map<Color>()) if (out == 0 && m_color == Point_set::Property_map<CGAL::Color>())
out = -1; out = -1;
return out; return out;
} }
@ -532,7 +532,7 @@ void Point_set_item_classification::compute_features (std::size_t nb_scales, flo
if (normals) if (normals)
normal_map = m_points->point_set()->normal_map(); normal_map = m_points->point_set()->normal_map();
bool colors = (m_color != Point_set::Property_map<Color>()); bool colors = (m_color != Point_set::Property_map<CGAL::Color>());
Point_set::Property_map<boost::uint8_t> echo_map; Point_set::Property_map<boost::uint8_t> echo_map;
bool echo; bool echo;

View File

@ -30,7 +30,6 @@ class Point_set_item_classification : public Item_classification_base
public: public:
typedef Kernel::Point_3 Point_3; typedef Kernel::Point_3 Point_3;
typedef Kernel::Vector_3 Vector_3; typedef Kernel::Vector_3 Vector_3;
typedef CGAL::Classification::RGB_Color Color;
typedef Point_set::Point_map Point_map; typedef Point_set::Point_map Point_map;
typedef Point_set::Vector_map Vector_map; typedef Point_set::Vector_map Vector_map;
@ -398,9 +397,12 @@ class Point_set_item_classification : public Item_classification_base
std::vector<Cluster> m_clusters; std::vector<Cluster> m_clusters;
Point_set::Property_map<unsigned char> m_red;
Point_set::Property_map<unsigned char> m_green;
Point_set::Property_map<unsigned char> m_blue;
Point_set::Property_map<CGAL::Color> m_color;
std::vector<std::vector<float> > m_label_probabilities; std::vector<std::vector<float> > m_label_probabilities;
Point_set::Property_map<Color> m_color;
Point_set::Property_map<int> m_training; Point_set::Property_map<int> m_training;
Point_set::Property_map<int> m_classif; Point_set::Property_map<int> m_classif;

View File

@ -36,34 +36,6 @@ public:
bool canSave(const CGAL::Three::Scene_item*); bool canSave(const CGAL::Three::Scene_item*);
bool save(const CGAL::Three::Scene_item*, QFileInfo fileinfo); bool save(const CGAL::Three::Scene_item*, QFileInfo fileinfo);
private:
void set_vcolors(SMesh* smesh, const std::vector<CGAL::Color>& colors)
{
typedef SMesh SMesh;
typedef boost::graph_traits<SMesh>::vertex_descriptor vertex_descriptor;
SMesh::Property_map<vertex_descriptor, CGAL::Color> vcolors =
smesh->property_map<vertex_descriptor, CGAL::Color >("v:color").first;
bool created;
boost::tie(vcolors, created) = smesh->add_property_map<SMesh::Vertex_index,CGAL::Color>("v:color",CGAL::Color(0,0,0));
assert(colors.size()==smesh->number_of_vertices());
int color_id = 0;
for(vertex_descriptor vd : vertices(*smesh))
vcolors[vd] = colors[color_id++];
}
void set_fcolors(SMesh* smesh, const std::vector<CGAL::Color>& colors)
{
typedef SMesh SMesh;
typedef boost::graph_traits<SMesh>::face_descriptor face_descriptor;
SMesh::Property_map<face_descriptor, CGAL::Color> fcolors =
smesh->property_map<face_descriptor, CGAL::Color >("f:color").first;
bool created;
boost::tie(fcolors, created) = smesh->add_property_map<SMesh::Face_index,CGAL::Color>("f:color",CGAL::Color(0,0,0));
assert(colors.size()==smesh->number_of_faces());
int color_id = 0;
for(face_descriptor fd : faces(*smesh))
fcolors[fd] = colors[color_id++];
}
}; };
bool Polyhedron_demo_ply_plugin::canLoad() const { bool Polyhedron_demo_ply_plugin::canLoad() const {
@ -116,6 +88,23 @@ Polyhedron_demo_ply_plugin::load(QFileInfo fileinfo) {
if (input_is_mesh) // Open mesh or polygon soup if (input_is_mesh) // Open mesh or polygon soup
{ {
// First try mesh
SMesh *surface_mesh = new SMesh();
std::string comments;
if (CGAL::read_ply (in, *surface_mesh, comments))
{
Scene_surface_mesh_item* sm_item = new Scene_surface_mesh_item(surface_mesh);
sm_item->setName(fileinfo.completeBaseName());
sm_item->comments() = comments;
QApplication::restoreOverrideCursor();
return sm_item;
}
in.clear();
in.seekg(0);
// else try polygon soup
std::vector<Kernel::Point_3> points; std::vector<Kernel::Point_3> points;
std::vector<std::vector<std::size_t> > polygons; std::vector<std::vector<std::size_t> > polygons;
std::vector<CGAL::Color> fcolors; std::vector<CGAL::Color> fcolors;
@ -127,29 +116,11 @@ Polyhedron_demo_ply_plugin::load(QFileInfo fileinfo) {
return NULL; return NULL;
} }
if (CGAL::Polygon_mesh_processing::is_polygon_soup_a_polygon_mesh (polygons)) Scene_polygon_soup_item* soup_item = new Scene_polygon_soup_item;
{ soup_item->setName(fileinfo.completeBaseName());
SMesh *surface_mesh = new SMesh(); soup_item->load (points, polygons, fcolors, vcolors);
CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh (points, polygons, QApplication::restoreOverrideCursor();
*surface_mesh); return soup_item;
if(!(vcolors.empty()))
set_vcolors(surface_mesh, vcolors);
if(!(fcolors.empty()))
set_fcolors(surface_mesh, fcolors);
Scene_surface_mesh_item* sm_item = new Scene_surface_mesh_item(surface_mesh);
sm_item->setName(fileinfo.completeBaseName());
QApplication::restoreOverrideCursor();
return sm_item;
}
else
{
Scene_polygon_soup_item* soup_item = new Scene_polygon_soup_item;
soup_item->setName(fileinfo.completeBaseName());
soup_item->load (points, polygons, fcolors, vcolors);
QApplication::restoreOverrideCursor();
return soup_item;
}
} }
else // Open point set else // Open point set
{ {
@ -212,10 +183,11 @@ bool Polyhedron_demo_ply_plugin::save(const CGAL::Three::Scene_item* item, QFile
return CGAL::write_PLY (out, soup_item->points(), soup_item->polygons()); return CGAL::write_PLY (out, soup_item->points(), soup_item->polygons());
// This plugin supports surface meshes // This plugin supports surface meshes
const Scene_surface_mesh_item* sm_item = Scene_surface_mesh_item* sm_item =
qobject_cast<const Scene_surface_mesh_item*>(item); const_cast<Scene_surface_mesh_item*>(qobject_cast<const Scene_surface_mesh_item*>(item));
if (sm_item) if (sm_item)
return CGAL::write_PLY (out, *(sm_item->polyhedron())); return CGAL::write_ply (out, *(sm_item->polyhedron()), sm_item->comments());
return false; return false;
} }

View File

@ -619,7 +619,7 @@ bool Scene_points_with_normal_item::read_ply_point_set(std::istream& stream)
d->m_points->clear(); d->m_points->clear();
bool ok = stream && bool ok = stream &&
CGAL::read_ply_point_set (stream, *(d->m_points), &(d->m_comments)) && CGAL::read_ply_point_set (stream, *(d->m_points), d->m_comments) &&
!isEmpty(); !isEmpty();
d->point_Slider->setValue(CGAL::Three::Three::getDefaultPointSize()); d->point_Slider->setValue(CGAL::Three::Three::getDefaultPointSize());
std::cerr << d->m_points->info(); std::cerr << d->m_points->info();
@ -653,7 +653,7 @@ bool Scene_points_with_normal_item::write_ply_point_set(std::ostream& stream, bo
if (binary) if (binary)
CGAL::set_binary_mode (stream); CGAL::set_binary_mode (stream);
CGAL::write_ply_point_set (stream, *(d->m_points), &(d->m_comments)); CGAL::write_ply_point_set (stream, *(d->m_points), d->m_comments);
return true; return true;
} }

View File

@ -211,6 +211,8 @@ struct Scene_surface_mesh_item_priv{
mutable QList<double> text_ids; mutable QList<double> text_ids;
mutable std::vector<TextItem*> targeted_id; mutable std::vector<TextItem*> targeted_id;
std::string comments;
mutable bool has_fpatch_id; mutable bool has_fpatch_id;
mutable bool has_feature_edges; mutable bool has_feature_edges;
mutable bool floated; mutable bool floated;
@ -1050,6 +1052,9 @@ Scene_surface_mesh_item::~Scene_surface_mesh_item()
SMesh* Scene_surface_mesh_item::polyhedron() { return d->smesh_; } SMesh* Scene_surface_mesh_item::polyhedron() { return d->smesh_; }
const SMesh* Scene_surface_mesh_item::polyhedron() const { return d->smesh_; } const SMesh* Scene_surface_mesh_item::polyhedron() const { return d->smesh_; }
std::string& Scene_surface_mesh_item::comments() { return d->comments; }
const std::string& Scene_surface_mesh_item::comments() const { return d->comments; }
void Scene_surface_mesh_item::compute_bbox()const void Scene_surface_mesh_item::compute_bbox()const
{ {
SMesh::Property_map<vertex_descriptor, Point_3> pprop = d->smesh_->points(); SMesh::Property_map<vertex_descriptor, Point_3> pprop = d->smesh_->points();

View File

@ -89,6 +89,10 @@ public:
Face_graph* face_graph() { return polyhedron(); } Face_graph* face_graph() { return polyhedron(); }
const Face_graph* face_graph() const { return polyhedron(); } const Face_graph* face_graph() const { return polyhedron(); }
// Gets PLY comments (empty if mesh not originated from PLY input)
std::string& comments();
const std::string& comments() const;
void invalidate_aabb_tree(); void invalidate_aabb_tree();
void invalidateOpenGLBuffers()Q_DECL_OVERRIDE; void invalidateOpenGLBuffers()Q_DECL_OVERRIDE;
void invalidate(Gl_data_names name); void invalidate(Gl_data_names name);

View File

@ -23,6 +23,6 @@ typedef Polyhedron::Halfedge_handle Halfedge_handle;
int main() { int main() {
Polyhedron P; Polyhedron P;
Halfedge_handle h = P.make_tetrahedron(); Halfedge_handle h = P.make_tetrahedron();
h->facet()->color = CGAL::RED; h->facet()->color = CGAL::red();
return 0; return 0;
} }

View File

@ -29,6 +29,6 @@ typedef Polyhedron::Halfedge_handle Halfedge_handle;
int main() { int main() {
Polyhedron P; Polyhedron P;
Halfedge_handle h = P.make_tetrahedron(); Halfedge_handle h = P.make_tetrahedron();
h->vertex()->color = CGAL::RED; h->vertex()->color = CGAL::red();
return 0; return 0;
} }

View File

@ -47,7 +47,7 @@ int main() {
Polyhedron P; Polyhedron P;
P.make_tetrahedron( p,q,r,s); P.make_tetrahedron( p,q,r,s);
CGAL::Geomview_stream geo; CGAL::Geomview_stream geo;
geo << CGAL::GREEN << P; geo << CGAL::green() << P;
// wait for a mouse click. // wait for a mouse click.
Point click; Point click;

View File

@ -20,7 +20,7 @@
#ifndef CGAL_IO_PLY_READER_H #ifndef CGAL_IO_PLY_READER_H
#define CGAL_IO_PLY_READER_H #define CGAL_IO_PLY_READER_H
#include <CGAL/IO/read_ply_points.h> #include <CGAL/IO/PLY.h>
namespace CGAL{ namespace CGAL{

View File

@ -20,7 +20,7 @@
#ifndef CGAL_IO_PLY_WRITER_H #ifndef CGAL_IO_PLY_WRITER_H
#define CGAL_IO_PLY_WRITER_H #define CGAL_IO_PLY_WRITER_H
#include <CGAL/IO/write_ply_points.h> #include <CGAL/IO/PLY.h>
namespace CGAL{ namespace CGAL{

View File

@ -112,7 +112,7 @@ public:
mWriter (out) mWriter (out)
,mDefaultDxfColor (255) ,mDefaultDxfColor (255)
,mDxfColor (255) ,mDxfColor (255)
,mCgalColor (WHITE) ,mCgalColor (white())
,mLayer ("0") ,mLayer ("0")
{ {
setup_initial_color_table(); setup_initial_color_table();
@ -305,15 +305,15 @@ protected:
void setup_initial_color_table() void setup_initial_color_table()
{ {
define_color(BLACK,0); define_color(black(),0);
define_color(RED,1); define_color(red(),1);
define_color(YELLOW,2); define_color(yellow(),2);
define_color(GREEN,3); define_color(green(),3);
define_color(PURPLE,4); define_color(purple(),4);
define_color(BLUE,5); define_color(blue(),5);
define_color(VIOLET,6); define_color(violet(),6);
define_color(WHITE,7); define_color(white(),7);
define_color(GRAY,8); define_color(gray(),8);
} }
}; };

View File

@ -547,25 +547,25 @@ void dump_to_dxf ( TestCase const& aCase )
{ {
if ( sVerbose ) if ( sVerbose )
cout << " Dumping input region. " << endl ; cout << " Dumping input region. " << endl ;
dump_region_to_dxf(*aCase.Inner.Input,BLUE,"Input",lDxf); dump_region_to_dxf(*aCase.Inner.Input,blue(),"Input",lDxf);
} }
if ( aCase.Inner.PartialSkeleton ) if ( aCase.Inner.PartialSkeleton )
{ {
if ( sVerbose ) if ( sVerbose )
cout << " Dumping inner skeleton." << endl ; cout << " Dumping inner skeleton." << endl ;
dump_skeleton_to_dxf(*aCase.Inner.PartialSkeleton,YELLOW,GREEN,PURPLE,GRAY,"InnerSkeleton",lDxf); dump_skeleton_to_dxf(*aCase.Inner.PartialSkeleton,yellow(),green(),purple(),gray(),"InnerSkeleton",lDxf);
} }
if ( aCase.Outer.PartialSkeleton ) if ( aCase.Outer.PartialSkeleton )
{ {
if ( sVerbose ) if ( sVerbose )
cout << " Dumping outer skeleton." << endl ; cout << " Dumping outer skeleton." << endl ;
dump_skeleton_to_dxf(*aCase.Outer.PartialSkeleton,YELLOW,GREEN,PURPLE,GRAY,"OuterSkeleton",lDxf); dump_skeleton_to_dxf(*aCase.Outer.PartialSkeleton,yellow(),green(),purple(),gray(),"OuterSkeleton",lDxf);
} }
dump_region_to_dxf(aCase.Inner.Contours,GRAY,"InnerOffset",lDxf); dump_region_to_dxf(aCase.Inner.Contours,gray(),"InnerOffset",lDxf);
dump_region_to_dxf(aCase.Outer.Contours,GRAY,"OuterOffset",lDxf); dump_region_to_dxf(aCase.Outer.Contours,gray(),"OuterOffset",lDxf);
} }

View File

@ -1,107 +0,0 @@
namespace CGAL {
/*!
\ingroup PkgStreamSupportRef
An object of the class `Color` is a color available
for drawing operations in many \cgal output streams.
Each color is defined by a triple of unsigned chars `(r,g,b)` with
0 \f$\le\f$ r,g,b \f$ \le \f$ 255, the so-called <I>rgb-value</I> of the color.
\sa `CGAL::Geomview_stream`
*/
class Color {
public:
/// \name Creation
/// @{
/*!
creates a color with rgb-value `(0,0,0)`, i.e.\ black.
*/
Color();
/*!
creates a color with rgb-value `(red,green,blue)`.
*/
Color(unsigned char red, unsigned char green, unsigned char blue);
/// @}
/// \name Operations
/// @{
/*!
Test for equality: Two colors are equal, iff their
rgb-values are equal.
*/
bool operator==(const Color &q) const;
/*!
Test for inequality.
*/
bool operator!=(const Color &q) const;
/*!
returns the red component of `c`.
*/
unsigned char red() const;
/*!
returns the green component of `c`.
*/
unsigned char green() const;
/*!
returns the blue component of `c`.
*/
unsigned char blue() const;
/// @}
/// \name Constants
/// The following constants are predefined:
/// @{
/*!
Black.
*/
const Color BLACK = Color(0, 0, 0);
/*!
White.
*/
const Color WHITE = Color(255, 255, 255);
/*!
Red.
*/
const Color RED = Color(255, 0, 0);
/*!
Green.
*/
const Color GREEN = Color(0, 255, 0);
/*!
Blue.
*/
const Color BLUE = Color(0, 0, 255);
/*!
Violet.
*/
const Color VIOLET = Color(255, 0, 255);
/*!
Orange.
*/
const Color ORANGE = Color(255, 170, 0);
/// @}
}; /* end Color */
} /* end namespace CGAL */

View File

@ -1,4 +1,5 @@
@INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS} @INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS}
PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - IO Streams" PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - IO Streams"
INPUT += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/IO/Color.h

View File

@ -23,74 +23,327 @@
// //
// Author(s) : Andreas Fabri // Author(s) : Andreas Fabri
#include <CGAL/config.h>
#ifndef CGAL_COLOR_H #ifndef CGAL_COLOR_H
#define CGAL_COLOR_H #define CGAL_COLOR_H
#include <CGAL/config.h>
#include <CGAL/array.h>
namespace CGAL { namespace CGAL {
class Color {
public:
Color(): _red(120), _green(120), _blue(120), _alpha(120) {}
Color(unsigned char red,
unsigned char green,
unsigned char blue,
unsigned char alpha = 120)
: _red(red), _green(green), _blue(blue), _alpha(alpha)
{}
unsigned char r() const {return _red;} /*!
unsigned char g() const {return _green;} \ingroup PkgStreamSupportRef
unsigned char b() const {return _blue;}
unsigned char red() const {return _red;} An object of the class `Color` is a color available for drawing
unsigned char green() const {return _green;} operations in many \cgal output streams. Each color is defined by a
unsigned char blue() const {return _blue;} 4 unsigned chars `(r,g,b,a)` with 0 \f$\le\f$ r,g,b,a \f$ \le \f$
unsigned char alpha() const {return _alpha;} 255, the so-called <I>rgba-value</I> of the color.
void set_alpha(unsigned char a) {_alpha=a;}
bool operator==(const Color &c) const
{
return ( (red() == c.red()) &&
(green() == c.green()) &&
(blue() == c.blue()) );
}
bool operator!=(const Color &c) const The alpha parameter (representing transparency) is often ignored and
{ left to its default value (255 = no transparency), which is why we
return !( (*this) == c); often refer to the <I>rgb-value</I> of the color.
}
\sa `CGAL::Geomview_stream`
*/
class Color
{
private: private:
unsigned char _red;
unsigned char _green; cpp11::array<unsigned char, 4> m_data;
unsigned char _blue;
unsigned char _alpha; public:
/// \name Creation
/// @{
/*!
creates a color with rgba-value `(0,0,0,255)`, i.e.\ black.
*/
Color()
{
set_rgb (0, 0, 0, 255);
}
/*!
creates a color with rgba-value `(red,green,blue,alpha)`.
*/
Color(unsigned char red,
unsigned char green,
unsigned char blue,
unsigned char alpha = 255)
{
set_rgb (red, green, blue, alpha);
}
/// @}
/// \name Component Access
/// @{
/*!
returns the red component.
*/
unsigned char red() const { return m_data[0]; }
/*!
returns a reference on the red component.
*/
unsigned char& red() { return m_data[0]; }
/*!
returns the green component.
*/
unsigned char green() const { return m_data[1]; }
/*!
returns a reference on the green component.
*/
unsigned char& green() { return m_data[1]; }
/*!
returns the blue component.
*/
unsigned char blue() const { return m_data[2]; }
/*!
returns a reference on the blue component.
*/
unsigned char& blue() { return m_data[2]; }
/*!
returns the alpha component.
*/
unsigned char alpha() const { return m_data[3]; }
/*!
returns a reference on the alpha component.
*/
unsigned char& alpha() { return m_data[3]; }
/// \cond SKIP_IN_MANUAL
unsigned char r() const { return red(); }
unsigned char g() const { return green(); }
unsigned char b() const { return blue(); }
unsigned char a() const { return alpha(); }
/// \endcond
/// @}
/// \name Array Access
/// @{
/*!
returns the \f$i^{th}\f$ component of the rgb color (the
\f$0^{th}\f$ is red, the \f$1^{st}\f$ is blue, etc.).
*/
unsigned char operator[] (std::size_t i) const { return m_data[i]; }
/*!
returns a reference on the \f$i^{th}\f$ component of `c` (the
\f$0^{th}\f$ is red, the \f$1^{st}\f$ is blue, etc.).
*/
unsigned char& operator[] (std::size_t i) { return m_data[i]; }
/*!
returns the array with rgba values.
*/
const cpp11::array<unsigned char, 4>& to_rgba() const { return m_data; }
/*!
returns the array with rgb values.
*/
const cpp11::array<unsigned char, 3>& to_rgb() const
{
return reinterpret_cast<const cpp11::array<unsigned char, 3>&>(m_data);
}
/*!
computes the hsv (hue, saturation, value) values and returns an
array representing them as float values between 0 and 1.
*/
cpp11::array<double, 3> to_hsv() const
{
double r = (double)(m_data[0]) / 255.;
double g = (double)(m_data[1]) / 255.;
double b = (double)(m_data[2]) / 255.;
double Cmax = (std::max) (r, (std::max) (g, b));
double Cmin = (std::min) (r, (std::min) (g, b));
double delta = Cmax - Cmin;
double H = 0.;
if (delta != 0.)
{
if (Cmax == r)
H = 60. * ((g - b) / delta);
else if (Cmax == g)
H = 60. * (((b - r) / delta) + 2.);
else
H = 60. * (((r - g) / delta) + 4.);
}
if (H < 0.) H += 360.;
double S = (Cmax == 0. ? 0. : 100. * (delta / Cmax));
double V = 100. * Cmax;
return make_array(H,S,V);
}
/// \name Modification
/// @{
/*!
replaces the rgb values of the colors by the one given as parameters.
*/
void set_rgb (unsigned char red,
unsigned char green,
unsigned char blue,
unsigned char alpha = 255)
{
m_data[0] = red;
m_data[1] = green;
m_data[2] = blue;
m_data[3] = alpha;
}
/*!
replaces the rgb values of the colors by the conversion to rgb of
the hsv values given as parameters.
Double values given as parameters should take range between 0 and 1.
*/
void set_hsv (double hue,
double saturation,
double value,
unsigned char alpha = 255)
{
saturation /= 100.;
value /= 100.;
double C = value*saturation;
int hh = (int)(hue/60.);
double X = C * (1-std::abs (hh % 2 - 1));
double r = 0, g = 0, b = 0;
if( hh>=0 && hh<1 )
{
r = C;
g = X;
}
else if( hh>=1 && hh<2 )
{
r = X;
g = C;
}
else if( hh>=2 && hh<3 )
{
g = C;
b = X;
}
else if( hh>=3 && hh<4 )
{
g = X;
b = C;
}
else if( hh>=4 && hh<5 )
{
r = X;
b = C;
}
else
{
r = C;
b = X;
}
double m = value-C;
r += m;
g += m;
b += m;
r *= 255.0;
g *= 255.0;
b *= 255.0;
m_data[0] = (unsigned char)r;
m_data[1] = (unsigned char)g;
m_data[2] = (unsigned char)b;
m_data[3] = alpha;
}
/// @}
}; };
#ifndef CGAL_HEADER_ONLY /*!
CGAL_EXPORT extern const Color BLACK ; Constructs Color(0,0,0).
CGAL_EXPORT extern const Color WHITE ; \relates Color
CGAL_EXPORT extern const Color GRAY ; */
inline Color black() { return Color(0,0,0); }
CGAL_EXPORT extern const Color RED ; /*!
CGAL_EXPORT extern const Color GREEN ; Constructs Color(0,0,255).
\relates Color
*/
inline Color blue() { return Color(0,0,255); }
CGAL_EXPORT extern const Color DEEPBLUE; /*!
CGAL_EXPORT extern const Color BLUE ; Constructs Color(10,0,100).
CGAL_EXPORT extern const Color PURPLE ; \relates Color
CGAL_EXPORT extern const Color VIOLET ; */
inline Color deep_blue() { return Color(10,0,100); }
CGAL_EXPORT extern const Color ORANGE ; /*!
CGAL_EXPORT extern const Color YELLOW ; Constructs Color(100,100,100).
\relates Color
*/
inline Color gray() { return Color(100,100,100); }
/*!
Constructs Color(0,255,0).
\relates Color
*/
inline Color green() { return Color(0,255,0); }
/*!
Constructs Color(235,150,0).
\relates Color
*/
inline Color orange() { return Color(235,150,0); }
/*!
Constructs Color(100,0,70).
\relates Color
*/
inline Color purple() { return Color(100,0,70); }
/*!
Constructs Color(255,0,0).
\relates Color
*/
inline Color red() { return Color(255,0,0); }
/*!
Constructs Color(255,0,255).
\relates Color
*/
inline Color violet() { return Color(255,0,255); }
/*!
Constructs Color(255,255,255).
\relates Color
*/
inline Color white() { return Color(255,255,255); }
/*!
Constructs Color(255,255,0).
\relates Color
*/
inline Color yellow() { return Color(255,255,0); }
#endif // CGAL_HEADER_ONLY
} //namespace CGAL } //namespace CGAL
#ifdef CGAL_HEADER_ONLY
#include <CGAL/IO/Color_impl.h>
#endif // CGAL_HEADER_ONLY
#endif // CGAL_COLOR_H #endif // CGAL_COLOR_H

View File

@ -1,43 +0,0 @@
// Copyright (c) 1997
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 3 of the License,
// or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0+
//
//
// Author(s) : Andreas Fabri, Hervé Brönnimann
namespace CGAL {
const Color BLACK = Color(0, 0, 0);
const Color WHITE = Color(255, 255, 255);
const Color GRAY = Color(100,100,100);
const Color GREEN = Color(0, 255, 0);
const Color DEEPBLUE = Color(10, 0, 100);
const Color BLUE = Color(0, 0, 255);
const Color VIOLET = Color(255, 0, 255);
const Color PURPLE = Color(100, 0, 70);
const Color RED = Color(255, 0, 0);
const Color ORANGE = Color(235, 150, 0);
const Color YELLOW = Color(255, 255, 0);
} //namespace CGAL

View File

@ -0,0 +1,973 @@
// Copyright (c) 2015 Geometry Factory
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// 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 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0+
//
// Author(s) : Simon Giraudot
#ifndef CGAL_IO_PLY_H
#define CGAL_IO_PLY_H
#include <CGAL/Kernel_traits.h>
#include <CGAL/IO/io.h>
#include <tuple>
#include <iostream>
#include <sstream>
#include <string>
#define TRY_TO_GENERATE_PROPERTY(STD_TYPE, T_TYPE, TYPE) \
if (type == STD_TYPE || type == T_TYPE) \
m_elements.back().add_property (new PLY_read_typed_number< TYPE > (name, format))
#define TRY_TO_GENERATE_SIZED_LIST_PROPERTY(STD_SIZE_TYPE, T_SIZE_TYPE, SIZE_TYPE, STD_INDEX_TYPE, T_INDEX_TYPE, INDEX_TYPE) \
if ((size_type == STD_SIZE_TYPE || size_type == T_SIZE_TYPE) && \
(index_type == STD_INDEX_TYPE || index_type == T_INDEX_TYPE)) \
m_elements.back().add_property (new PLY_read_typed_list_with_typed_size< SIZE_TYPE , INDEX_TYPE > (name, format))
#define TRY_TO_GENERATE_LIST_PROPERTY(STD_INDEX_TYPE, T_INDEX_TYPE, INDEX_TYPE) \
TRY_TO_GENERATE_SIZED_LIST_PROPERTY("uchar", "uint8", boost::uint8_t, STD_INDEX_TYPE, T_INDEX_TYPE, INDEX_TYPE); \
else TRY_TO_GENERATE_SIZED_LIST_PROPERTY("ushort", "uint16", boost::uint16_t, STD_INDEX_TYPE, T_INDEX_TYPE, INDEX_TYPE); \
else TRY_TO_GENERATE_SIZED_LIST_PROPERTY("uint", "uint32", boost::uint32_t, STD_INDEX_TYPE, T_INDEX_TYPE, INDEX_TYPE)
/// \cond SKIP_IN_MANUAL
namespace CGAL {
// PLY types:
// name type number of bytes
// ---------------------------------------
// char character 1
// uchar unsigned character 1
// short short integer 2
// ushort unsigned short integer 2
// int integer 4
// uint unsigned integer 4
// float single-precision float 4
// double double-precision float 8
template <typename T>
struct PLY_property
{
typedef T type;
const char* name;
PLY_property (const char* name) : name (name) { }
};
// Use a double property for all kernels...
template <typename FT> struct Convert_FT { typedef double type; };
// ...except if kernel uses type float
template <> struct Convert_FT<float> { typedef float type; };
template <typename PointOrVectorMap>
struct Get_FT_from_map
{
typedef typename Convert_FT
<typename Kernel_traits
<typename boost::property_traits
<PointOrVectorMap>::value_type>::Kernel::FT>::type type;
};
template <typename PointMap>
std::tuple<PointMap,
typename Kernel_traits<typename PointMap::value_type>::Kernel::Construct_point_3,
PLY_property<typename Get_FT_from_map<PointMap>::type>,
PLY_property<typename Get_FT_from_map<PointMap>::type>,
PLY_property<typename Get_FT_from_map<PointMap>::type> >
make_ply_point_reader(PointMap point_map)
{
return std::make_tuple (point_map, typename Kernel_traits<typename PointMap::value_type>::Kernel::Construct_point_3(),
PLY_property<typename Get_FT_from_map<PointMap>::type>("x"),
PLY_property<typename Get_FT_from_map<PointMap>::type>("y"),
PLY_property<typename Get_FT_from_map<PointMap>::type>("z"));
}
template <typename VectorMap>
std::tuple<VectorMap,
typename Kernel_traits<typename VectorMap::value_type>::Kernel::Construct_vector_3,
PLY_property<typename Get_FT_from_map<VectorMap>::type>,
PLY_property<typename Get_FT_from_map<VectorMap>::type>,
PLY_property<typename Get_FT_from_map<VectorMap>::type> >
make_ply_normal_reader(VectorMap normal_map)
{
return std::make_tuple (normal_map, typename Kernel_traits<typename VectorMap::value_type>::Kernel::Construct_vector_3(),
PLY_property<typename Get_FT_from_map<VectorMap>::type>("nx"),
PLY_property<typename Get_FT_from_map<VectorMap>::type>("ny"),
PLY_property<typename Get_FT_from_map<VectorMap>::type>("nz"));
}
template <typename PointMap>
std::tuple<PointMap,
PLY_property<typename Get_FT_from_map<PointMap>::type>,
PLY_property<typename Get_FT_from_map<PointMap>::type>,
PLY_property<typename Get_FT_from_map<PointMap>::type> >
make_ply_point_writer(PointMap point_map)
{
return std::make_tuple (point_map,
PLY_property<typename Get_FT_from_map<PointMap>::type>("x"),
PLY_property<typename Get_FT_from_map<PointMap>::type>("y"),
PLY_property<typename Get_FT_from_map<PointMap>::type>("z"));
}
template <typename VectorMap>
std::tuple<VectorMap,
PLY_property<typename Get_FT_from_map<VectorMap>::type>,
PLY_property<typename Get_FT_from_map<VectorMap>::type>,
PLY_property<typename Get_FT_from_map<VectorMap>::type> >
make_ply_normal_writer(VectorMap normal_map)
{
return std::make_tuple (normal_map,
PLY_property<typename Get_FT_from_map<VectorMap>::type>("nx"),
PLY_property<typename Get_FT_from_map<VectorMap>::type>("ny"),
PLY_property<typename Get_FT_from_map<VectorMap>::type>("nz"));
}
namespace internal {
namespace PLY {
class PLY_read_number
{
protected:
std::string m_name;
std::size_t m_format;
public:
PLY_read_number (std::string name, std::size_t format)
: m_name (name), m_format (format) { }
virtual ~PLY_read_number() { }
const std::string& name () const { return m_name; }
virtual void get (std::istream& stream) const = 0;
// The two following functions prevent the stream to only extract
// ONE character (= what the types char imply) by requiring
// explicitely an integer object when reading the stream
void read_ascii (std::istream& stream, char& c) const
{
short s;
stream >> s;
c = static_cast<char>(s);
}
void read_ascii (std::istream& stream, signed char& c) const
{
short s;
stream >> s;
c = static_cast<signed char>(s);
}
void read_ascii (std::istream& stream, unsigned char& c) const
{
unsigned short s;
stream >> s;
c = static_cast<unsigned char>(s);
}
void read_ascii (std::istream& stream, float& t) const
{
stream >> iformat(t);
}
void read_ascii (std::istream& stream, double& t) const
{
stream >> iformat(t);
}
// Default template when Type is not a char type
template <typename Type>
void read_ascii (std::istream& stream, Type& t) const
{
stream >> t;
}
template <typename Type>
Type read (std::istream& stream) const
{
if (m_format == 0) // Ascii
{
Type t;
read_ascii (stream, t);
return t;
}
else // Binary (2 = little endian)
{
union
{
char uChar[sizeof (Type)];
Type type;
} buffer;
std::size_t size = sizeof (Type);
stream.read(buffer.uChar, size);
if (m_format == 2) // Big endian
{
for (std::size_t i = 0; i < size / 2; ++ i)
{
unsigned char tmp = buffer.uChar[i];
buffer.uChar[i] = buffer.uChar[size - 1 - i];
buffer.uChar[size - 1 - i] = tmp;
}
}
return buffer.type;
}
return Type();
}
};
template <typename Type>
class PLY_read_typed_number : public PLY_read_number
{
mutable Type m_buffer;
public:
PLY_read_typed_number (std::string name, std::size_t format)
: PLY_read_number (name, format)
{
}
void get (std::istream& stream) const
{
m_buffer = (this->read<Type> (stream));
}
const Type& buffer() const
{
return m_buffer;
}
};
template <typename Type>
class PLY_read_typed_list : public PLY_read_number
{
protected:
mutable std::vector<Type> m_buffer;
public:
PLY_read_typed_list (std::string name, std::size_t format)
: PLY_read_number (name, format)
{
}
virtual void get (std::istream& stream) const = 0;
const std::vector<Type>& buffer() const
{
return m_buffer;
}
};
template <typename SizeType, typename IndexType>
class PLY_read_typed_list_with_typed_size
: public PLY_read_typed_list<IndexType>
{
public:
PLY_read_typed_list_with_typed_size (std::string name, std::size_t format)
: PLY_read_typed_list<IndexType> (name, format)
{
}
void get (std::istream& stream) const
{
std::size_t size = static_cast<std::size_t>(this->template read<SizeType>(stream));
this->m_buffer.resize (size);
for (std::size_t i = 0; i < size; ++ i)
this->m_buffer[i] = this->template read<IndexType> (stream);
}
};
class PLY_element
{
std::string m_name;
std::size_t m_number;
std::vector<PLY_read_number*> m_properties;
public:
PLY_element (const std::string& name, std::size_t number)
: m_name (name), m_number (number)
{ }
PLY_element (const PLY_element& other)
: m_name (other.m_name), m_number (other.m_number), m_properties (other.m_properties)
{
const_cast<PLY_element&>(other).m_properties.clear();
}
PLY_element& operator= (const PLY_element& other)
{
m_name = other.m_name;
m_number = other.m_number;
m_properties = other.m_properties;
const_cast<PLY_element&>(other).m_properties.clear();
return *this;
}
~PLY_element()
{
for (std::size_t i = 0; i < m_properties.size(); ++ i)
delete m_properties[i];
}
const std::string& name() const { return m_name; }
std::size_t number_of_items() const { return m_number; }
std::size_t number_of_properties() const { return m_properties.size(); }
PLY_read_number* property (std::size_t idx) { return m_properties[idx]; }
void add_property (PLY_read_number* read_number)
{
m_properties.push_back (read_number);
}
template <typename Type>
bool has_property (const char* tag)
{
return has_property (tag, Type());
}
template <typename Type>
bool has_property (const char* tag, const std::vector<Type>&)
{
for (std::size_t i = 0; i < number_of_properties(); ++ i)
if (m_properties[i]->name () == tag)
return (dynamic_cast<PLY_read_typed_list<Type>*>(m_properties[i]) != NULL);
return false;
}
template <typename Type>
bool has_property (const char* tag, Type)
{
for (std::size_t i = 0; i < number_of_properties(); ++ i)
if (m_properties[i]->name () == tag)
return (dynamic_cast<PLY_read_typed_number<Type>*>(m_properties[i]) != NULL);
return false;
}
bool has_property (const char* tag, double)
{
for (std::size_t i = 0; i < number_of_properties(); ++ i)
if (m_properties[i]->name () == tag)
return (dynamic_cast<PLY_read_typed_number<double>*>(m_properties[i]) != NULL
|| dynamic_cast<PLY_read_typed_number<float>*>(m_properties[i]) != NULL);
return false;
}
template <typename Type>
void assign (Type& t, const char* tag)
{
for (std::size_t i = 0; i < number_of_properties (); ++ i)
if (m_properties[i]->name () == tag)
{
PLY_read_typed_number<Type>*
property = dynamic_cast<PLY_read_typed_number<Type>*>(m_properties[i]);
CGAL_assertion (property != NULL);
t = property->buffer();
return;
}
}
template <typename Type>
void assign (std::vector<Type>& t, const char* tag)
{
for (std::size_t i = 0; i < number_of_properties (); ++ i)
if (m_properties[i]->name () == tag)
{
PLY_read_typed_list<Type>*
property = dynamic_cast<PLY_read_typed_list<Type>*>(m_properties[i]);
CGAL_assertion (property != NULL);
t = property->buffer();
return;
}
}
void assign (double& t, const char* tag)
{
for (std::size_t i = 0; i < number_of_properties (); ++ i)
if (m_properties[i]->name () == tag)
{
PLY_read_typed_number<double>*
property_double = dynamic_cast<PLY_read_typed_number<double>*>(m_properties[i]);
if (property_double == NULL)
{
PLY_read_typed_number<float>*
property_float = dynamic_cast<PLY_read_typed_number<float>*>(m_properties[i]);
CGAL_assertion (property_float != NULL);
t = property_float->buffer();
}
else
t = property_double->buffer();
return;
}
}
};
class PLY_reader
{
std::vector<PLY_element> m_elements;
std::string m_comments;
public:
PLY_reader () { }
std::size_t number_of_elements() const { return m_elements.size(); }
PLY_element& element (std::size_t idx)
{
return m_elements[idx];
}
const std::string& comments() const { return m_comments; }
template <typename Stream>
bool init (Stream& stream)
{
std::size_t lineNumber = 0; // current line number
enum Format { ASCII = 0, BINARY_LITTLE_ENDIAN = 1, BINARY_BIG_ENDIAN = 2};
Format format = ASCII;
std::string line;
std::istringstream iss;
while (getline (stream,line))
{
iss.clear();
iss.str (line);
++ lineNumber;
// Reads file signature on first line
if (lineNumber == 1)
{
std::string signature;
if (!(iss >> signature) || (signature != "ply"))
{
// if wrong file format
std::cerr << "Error: incorrect file format line " << lineNumber << " of file" << std::endl;
return false;
}
}
// Reads format on 2nd line
else if (lineNumber == 2)
{
std::string tag, format_string, version;
if ( !(iss >> tag >> format_string >> version) )
{
std::cerr << "Error line " << lineNumber << " of file" << std::endl;
return false;
}
if (format_string == "ascii") format = ASCII;
else if (format_string == "binary_little_endian") format = BINARY_LITTLE_ENDIAN;
else if (format_string == "binary_big_endian") format = BINARY_BIG_ENDIAN;
else
{
std::cerr << "Error: unknown file format \"" << format_string << "\" line " << lineNumber << std::endl;
return false;
}
}
// Comments and vertex properties
else
{
std::string keyword;
if (!(iss >> keyword))
{
std::cerr << "Error line " << lineNumber << " of file" << std::endl;
return false;
}
if (keyword == "property")
{
std::string type, name;
if (!(iss >> type >> name))
{
std::cerr << "Error line " << lineNumber << " of file" << std::endl;
return false;
}
if (type == "list") // Special case
{
std::string size_type = name;
std::string index_type;
name.clear();
if (!(iss >> index_type >> name))
{
std::cerr << "Error line " << lineNumber << " of file" << std::endl;
return false;
}
TRY_TO_GENERATE_LIST_PROPERTY ("char", "int8", boost::int8_t);
else TRY_TO_GENERATE_LIST_PROPERTY ("uchar", "uint8", boost::uint8_t);
else TRY_TO_GENERATE_LIST_PROPERTY ("short", "int16", boost::int16_t);
else TRY_TO_GENERATE_LIST_PROPERTY ("ushort", "uint16", boost::uint16_t);
else TRY_TO_GENERATE_LIST_PROPERTY ("int", "int32", boost::int32_t);
else TRY_TO_GENERATE_LIST_PROPERTY ("uint", "uint32", boost::uint32_t);
else TRY_TO_GENERATE_LIST_PROPERTY ("float", "float32", float);
else TRY_TO_GENERATE_LIST_PROPERTY ("double", "float64", double);
}
else
{
TRY_TO_GENERATE_PROPERTY ("char", "int8", boost::int8_t);
else TRY_TO_GENERATE_PROPERTY ("uchar", "uint8", boost::uint8_t);
else TRY_TO_GENERATE_PROPERTY ("short", "int16", boost::int16_t);
else TRY_TO_GENERATE_PROPERTY ("ushort", "uint16", boost::uint16_t);
else TRY_TO_GENERATE_PROPERTY ("int", "int32", boost::int32_t);
else TRY_TO_GENERATE_PROPERTY ("uint", "uint32", boost::uint32_t);
else TRY_TO_GENERATE_PROPERTY ("float", "float32", float);
else TRY_TO_GENERATE_PROPERTY ("double", "float64", double);
}
continue;
}
else if (keyword == "comment")
{
std::string str = iss.str();
if (str.size() > 8)
{
std::copy (str.begin() + 8, str.end(), std::back_inserter (m_comments));
m_comments += "\n";
}
}
else if (keyword == "element")
{
std::string type;
std::size_t number;
if (!(iss >> type >> number))
{
std::cerr << "Error line " << lineNumber << " of file" << std::endl;
return false;
}
m_elements.push_back (PLY_element(type, number));
}
// When end_header is reached, stop loop and begin reading points
else if (keyword == "end_header")
break;
}
}
return true;
}
~PLY_reader ()
{
}
};
template <class Reader, class T>
void get_value(Reader& r, T& v, PLY_property<T>& wrapper)
{
return r.assign(v, wrapper.name);
}
template <std::size_t N>
struct Filler
{
template <class Reader, class Value_tuple, class PLY_property_tuple>
static void fill(Reader& r, Value_tuple& values, PLY_property_tuple wrappers)
{
get_value(r, std::get<N>(values), std::get<N+2>(wrappers));
Filler<N-1>::fill(r, values, wrappers);
}
};
template<int ...>
struct seq { };
template<int N, int ...S>
struct gens : gens<N-1, N-1, S...> { };
template<int ...S>
struct gens<0, S...> {
typedef seq<S...> type;
};
template<class ValueType, class Functor, class Tuple, int ...S>
ValueType call_functor(Functor f, Tuple t, seq<S...>) {
return f(std::get<S>(t) ...);
}
template <class ValueType, class Functor, typename ... T>
ValueType call_functor(Functor f, std::tuple<T...>& t)
{
return call_functor<ValueType>(f, t, typename gens<sizeof...(T)>::type());
}
template<>
struct Filler<0>
{
template <class Reader, class Value_tuple, class PLY_property_tuple>
static void fill(Reader& r, Value_tuple& values, PLY_property_tuple wrappers)
{
get_value(r, std::get<0>(values), std::get<2>(wrappers));
}
};
template <typename OutputValueType,
typename PropertyMap,
typename Constructor,
typename ... T>
void process_properties (PLY_element& element, OutputValueType& new_element,
std::tuple<PropertyMap, Constructor, PLY_property<T>...>&& current)
{
typedef typename PropertyMap::value_type PmapValueType;
std::tuple<T...> values;
Filler<sizeof...(T)-1>::fill(element, values, current);
PmapValueType new_value = call_functor<PmapValueType>(std::get<1>(current), values);
put (std::get<0>(current), new_element, new_value);
}
template <typename OutputValueType,
typename PropertyMap,
typename Constructor,
typename ... T,
typename NextPropertyBinder,
typename ... PropertyMapBinders>
void process_properties (PLY_element& element, OutputValueType& new_element,
std::tuple<PropertyMap, Constructor, PLY_property<T>...>&& current,
NextPropertyBinder&& next,
PropertyMapBinders&& ... properties)
{
typedef typename PropertyMap::value_type PmapValueType;
std::tuple<T...> values;
Filler<sizeof...(T)-1>::fill(element, values, current);
PmapValueType new_value = call_functor<PmapValueType>(std::get<1>(current), values);
put (std::get<0>(current), new_element, new_value);
process_properties (element, new_element, std::forward<NextPropertyBinder>(next),
std::forward<PropertyMapBinders>(properties)...);
}
template <typename OutputValueType, typename PropertyMap, typename T>
void process_properties (PLY_element& element, OutputValueType& new_element,
std::pair<PropertyMap, PLY_property<T> >&& current)
{
T new_value = T();
element.assign (new_value, current.second.name);
put (current.first, new_element, new_value);
}
template <typename OutputValueType, typename PropertyMap, typename T,
typename NextPropertyBinder, typename ... PropertyMapBinders>
void process_properties (PLY_element& element, OutputValueType& new_element,
std::pair<PropertyMap, PLY_property<T> >&& current,
NextPropertyBinder&& next,
PropertyMapBinders&& ... properties)
{
T new_value = T();
element.assign (new_value, current.second.name);
put (current.first, new_element, new_value);
process_properties (element, new_element, std::forward<NextPropertyBinder>(next),
std::forward<PropertyMapBinders>(properties)...);
}
template <typename T> inline void property_header_type (std::ostream& stream)
{
CGAL_assertion_msg (false, "Unknown PLY type");
stream << "undefined_type";
}
template <> inline void property_header_type<char> (std::ostream& stream) { stream << "char"; }
template <> inline void property_header_type<signed char> (std::ostream& stream) { stream << "char"; }
template <> inline void property_header_type<unsigned char> (std::ostream& stream) { stream << "uchar"; }
template <> inline void property_header_type<short> (std::ostream& stream) { stream << "short"; }
template <> inline void property_header_type<unsigned short> (std::ostream& stream) { stream << "ushort"; }
template <> inline void property_header_type<int> (std::ostream& stream) { stream << "int"; }
template <> inline void property_header_type<unsigned int> (std::ostream& stream) { stream << "uint"; }
template <> inline void property_header_type<float> (std::ostream& stream) { stream << "float"; }
template <> inline void property_header_type<double> (std::ostream& stream) { stream << "double"; }
template <typename T>
void property_header (std::ostream& stream, const PLY_property<T>& prop)
{
stream << "property ";
property_header_type<T>(stream);
stream << " " << prop.name << std::endl;
}
template <typename T>
void property_header (std::ostream& stream, const PLY_property<std::vector<T> >& prop)
{
stream << "property list uchar ";
property_header_type<T>(stream);
stream << " " << prop.name << std::endl;
}
template <std::size_t N>
struct Properties_header
{
template <class PLY_property_tuple>
static void write(std::ostream& stream, PLY_property_tuple& wrappers)
{
Properties_header<N-1>::write(stream, wrappers);
property_header (stream, std::get<N+1>(wrappers));
}
};
template <>
struct Properties_header<0>
{
template <class PLY_property_tuple>
static void write(std::ostream& stream, PLY_property_tuple& wrappers)
{
property_header (stream, std::get<1>(wrappers));
}
};
template <typename PropertyMap,
typename ... T>
void output_property_header (std::ostream& stream,
std::tuple<PropertyMap, PLY_property<T>... >&& current)
{
Properties_header<sizeof...(T)-1>::write(stream, current);
}
template <typename PropertyMap,
typename T>
void output_property_header (std::ostream& stream,
std::pair<PropertyMap, PLY_property<T> >&& current)
{
property_header (stream, current.second);
}
template <typename PropertyMap,
typename T,
typename NextPropertyHandler,
typename ... PropertyHandler>
void output_property_header (std::ostream& stream,
std::pair<PropertyMap, PLY_property<T> >&& current,
NextPropertyHandler&& next,
PropertyHandler&& ... properties)
{
property_header (stream, current.second);
output_property_header (stream, std::forward<NextPropertyHandler>(next),
std::forward<PropertyHandler>(properties)...);
}
template <typename PropertyMap,
typename ... T,
typename NextPropertyHandler,
typename ... PropertyHandler>
void output_property_header (std::ostream& stream,
std::tuple<PropertyMap, PLY_property<T>... >&& current,
NextPropertyHandler&& next,
PropertyHandler&& ... properties)
{
Properties_header<sizeof...(T)-1>::write(stream, current);
output_property_header (stream, std::forward<NextPropertyHandler>(next),
std::forward<PropertyHandler>(properties)...);
}
template <typename ForwardIterator,
typename PropertyMap>
void property_write (std::ostream& stream, ForwardIterator it, PropertyMap map)
{
stream << CGAL::oformat(get (map, *it));
}
template <typename T>
inline T no_char_character (const T& t) { return t; }
inline int no_char_character (const char& t) { return int(t); }
inline int no_char_character (const signed char& t) { return int(t); }
inline int no_char_character (const unsigned char& t) { return int(t); }
template <typename ForwardIterator,
typename PropertyMap,
typename T>
void simple_property_write (std::ostream& stream, ForwardIterator it,
std::pair<PropertyMap, PLY_property<T> > map)
{
if (CGAL::get_mode(stream) == IO::ASCII)
stream << no_char_character(get (map.first, *it));
else
{
typename PropertyMap::value_type value = get(map.first, *it);
stream.write (reinterpret_cast<char*>(&value), sizeof(value));
}
}
template <typename ForwardIterator,
typename PropertyMap,
typename T>
void simple_property_write (std::ostream& stream, ForwardIterator it,
std::pair<PropertyMap, PLY_property<std::vector<T> > > map)
{
const typename PropertyMap::reference value = get(map.first, *it);
if (CGAL::get_mode(stream) == IO::ASCII)
{
stream << value.size();
for (std::size_t i = 0; i < value.size(); ++ i)
stream << " " << no_char_character(value[i]);
}
else
{
unsigned char size = static_cast<unsigned char>(value.size());
stream.write (reinterpret_cast<char*>(&size), sizeof(size));
for (std::size_t i = 0; i < value.size(); ++ i)
{
T t = T(value[i]);
stream.write (reinterpret_cast<char*>(&t), sizeof(t));
}
}
}
template <typename ForwardIterator,
typename PropertyMap,
typename ... T>
void output_properties (std::ostream& stream,
ForwardIterator it,
std::tuple<PropertyMap, PLY_property<T>... >&& current)
{
property_write (stream, it, std::get<0>(current));
if (get_mode(stream) == IO::ASCII)
stream << std::endl;
}
template <typename ForwardIterator,
typename PropertyMap,
typename T>
void output_properties (std::ostream& stream,
ForwardIterator it,
std::pair<PropertyMap, PLY_property<T> >&& current)
{
simple_property_write (stream, it, std::forward<std::pair<PropertyMap, PLY_property<T> > >(current));
if (get_mode(stream) == IO::ASCII)
stream << std::endl;
}
template <typename ForwardIterator,
typename PropertyMap,
typename T,
typename NextPropertyHandler,
typename ... PropertyHandler>
void output_properties (std::ostream& stream,
ForwardIterator it,
std::pair<PropertyMap, PLY_property<T> >&& current,
NextPropertyHandler&& next,
PropertyHandler&& ... properties)
{
simple_property_write (stream, it, current);
if (get_mode(stream) == IO::ASCII)
stream << " ";
output_properties (stream, it, std::forward<NextPropertyHandler>(next),
std::forward<PropertyHandler>(properties)...);
}
template <typename ForwardIterator,
typename PropertyMap,
typename ... T,
typename NextPropertyHandler,
typename ... PropertyHandler>
void output_properties (std::ostream& stream,
ForwardIterator it,
std::tuple<PropertyMap, PLY_property<T>... >&& current,
NextPropertyHandler&& next,
PropertyHandler&& ... properties)
{
property_write (stream, it, std::get<0>(current));
if (get_mode(stream) == IO::ASCII)
stream << " ";
output_properties (stream, it, std::forward<NextPropertyHandler>(next),
std::forward<PropertyHandler>(properties)...);
}
// Printer classes used by Point_set_3 and Surface_mesh (translate a
// property map to a PLY property)
template <typename Index>
class Abstract_property_printer
{
public:
virtual ~Abstract_property_printer() { }
virtual void print (std::ostream& stream, const Index& index) = 0;
};
template <typename Index, typename PropertyMap>
class Property_printer : public Abstract_property_printer<Index>
{
PropertyMap m_pmap;
public:
Property_printer (const PropertyMap& pmap) : m_pmap (pmap)
{
}
virtual void print(std::ostream& stream, const Index& index)
{
stream << get(m_pmap, index);
}
};
template <typename Index, typename PropertyMap,
typename Type = typename PropertyMap::value_type>
class Simple_property_printer : public Abstract_property_printer<Index>
{
PropertyMap m_pmap;
public:
Simple_property_printer (const PropertyMap& pmap) : m_pmap (pmap)
{
}
virtual void print(std::ostream& stream, const Index& index)
{
if (get_mode(stream) == IO::ASCII)
stream << get(m_pmap, index);
else
{
Type t = Type(get (m_pmap, index));
stream.write (reinterpret_cast<char*>(&t), sizeof(t));
}
}
};
template <typename Index, typename PropertyMap>
class Char_property_printer : public Abstract_property_printer<Index>
{
typedef typename PropertyMap::value_type Type;
PropertyMap m_pmap;
public:
Char_property_printer (const PropertyMap& pmap) : m_pmap (pmap)
{
}
virtual void print(std::ostream& stream, const Index& index)
{
if (get_mode(stream) == IO::ASCII)
stream << int(get(m_pmap, index));
else
{
Type t = get (m_pmap, index);
stream.write (reinterpret_cast<char*>(&t), sizeof(t));
}
}
};
} // namespace PLY
} // namespace internal
} // namespace CGAL
#endif // CGAL_IO_PLY_H

View File

@ -393,39 +393,45 @@ std::ostream& operator<<( std::ostream& out, const Color& col)
switch(get_mode(out)) { switch(get_mode(out)) {
case IO::ASCII : case IO::ASCII :
return out << static_cast<int>(col.red()) << ' ' return out << static_cast<int>(col.red()) << ' '
<< static_cast<int>(col.green()) << ' ' << static_cast<int>(col.green()) << ' '
<< static_cast<int>(col.blue()); << static_cast<int>(col.blue()) << ' '
<< static_cast<int>(col.alpha());
case IO::BINARY : case IO::BINARY :
write(out, static_cast<int>(col.red())); out.write(reinterpret_cast<const char*>(col.to_rgba().data()), 4);
write(out, static_cast<int>(col.green()));
write(out, static_cast<int>(col.blue()));
return out; return out;
default: default:
return out << "Color(" << static_cast<int>(col.red()) << ", " return out << "Color(" << static_cast<int>(col.red()) << ", "
<< static_cast<int>(col.green()) << ", " << static_cast<int>(col.green()) << ", "
<< static_cast<int>(col.blue()) << ')'; << static_cast<int>(col.blue()) << ", "
<< static_cast<int>(col.alpha()) << ")";
} }
} }
inline inline
std::istream &operator>>(std::istream &is, Color& col) std::istream &operator>>(std::istream &is, Color& col)
{ {
int r = 0, g = 0, b = 0; unsigned char r = 0, g = 0, b = 0, a = 0;
int ir = 0, ig = 0, ib = 0, ia = 0;
switch(get_mode(is)) { switch(get_mode(is)) {
case IO::ASCII : case IO::ASCII :
is >> r >> g >> b; is >> ir >> ig >> ib >> ia;
r = (unsigned char)ir;
g = (unsigned char)ig;
b = (unsigned char)ib;
a = (unsigned char)ia;
break; break;
case IO::BINARY : case IO::BINARY :
read(is, r); read(is, r);
read(is, g); read(is, g);
read(is, b); read(is, b);
read(is, a);
break; break;
default: default:
std::cerr << "" << std::endl; std::cerr << "" << std::endl;
std::cerr << "Stream must be in ascii or binary mode" << std::endl; std::cerr << "Stream must be in ascii or binary mode" << std::endl;
break; break;
} }
col = Color((unsigned char)r,(unsigned char)g,(unsigned char)b); col = Color(r,g,b,a);
return is; return is;
} }

View File

@ -26,6 +26,5 @@
#ifndef CGAL_HEADER_ONLY #ifndef CGAL_HEADER_ONLY
#include <CGAL/IO/Color.h> #include <CGAL/IO/Color.h>
#include <CGAL/IO/Color_impl.h>
#endif // CGAL_HEADER_ONLY #endif // CGAL_HEADER_ONLY

View File

@ -0,0 +1,727 @@
// Copyright (c) 2018 GeometryFactory Sarl (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// 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 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0+
//
//
// Author(s) : Simon Giraudot
#ifndef CGAL_SURFACE_MESH_IO_PLY
#define CGAL_SURFACE_MESH_IO_PLY
#include <CGAL/IO/PLY.h>
namespace CGAL {
namespace internal {
#if !defined(CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE) && !defined(CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES)
namespace PLY {
template <typename Point>
class Surface_mesh_filler
{
public:
typedef typename Kernel_traits<Point>::Kernel Kernel;
typedef typename Kernel::Vector_3 Vector;
typedef Surface_mesh<Point> Surface_mesh;
typedef typename Surface_mesh::Vertex_index Vertex_index;
typedef typename Surface_mesh::Face_index Face_index;
typedef typename Surface_mesh::Edge_index Edge_index;
typedef typename Surface_mesh::Halfedge_index Halfedge_index;
private:
struct Abstract_ply_property_to_surface_mesh_property
{
virtual ~Abstract_ply_property_to_surface_mesh_property() { }
virtual void assign (PLY_element& element, std::size_t index) = 0;
};
template <typename Simplex, typename Type>
class PLY_property_to_surface_mesh_property : public Abstract_ply_property_to_surface_mesh_property
{
typedef typename Surface_mesh::template Property_map<Simplex, Type> Map;
Map m_map;
std::string m_name;
public:
PLY_property_to_surface_mesh_property (Surface_mesh& sm, const std::string& name)
: m_name (name)
{
m_map = sm.template add_property_map<Simplex, Type>(prefix(Simplex()) + name).first;
}
virtual void assign (PLY_element& element, std::size_t index)
{
Type t{};
element.assign (t, m_name.c_str());
put(m_map, Simplex(index), t);
}
std::string prefix(Vertex_index) const { return "v:"; }
std::string prefix(Face_index) const { return "f:"; }
std::string prefix(Edge_index) const { return "e:"; }
std::string prefix(Halfedge_index) const { return "h:"; }
};
Surface_mesh& m_mesh;
std::vector<Vertex_index> m_map_v2v;
bool m_use_floats;
int m_normals;
typename Surface_mesh::template Property_map<Vertex_index, Vector> m_normal_map;
int m_vcolors;
typename Surface_mesh::template Property_map<Vertex_index, CGAL::Color> m_vcolor_map;
int m_fcolors;
typename Surface_mesh::template Property_map<Face_index, CGAL::Color> m_fcolor_map;
bool m_use_int32_t;
std::string m_index_tag;
std::vector<Abstract_ply_property_to_surface_mesh_property*> m_vertex_properties;
std::vector<Abstract_ply_property_to_surface_mesh_property*> m_face_properties;
std::vector<Abstract_ply_property_to_surface_mesh_property*> m_edge_properties;
std::vector<Abstract_ply_property_to_surface_mesh_property*> m_halfedge_properties;
public:
Surface_mesh_filler (Surface_mesh& mesh)
: m_mesh (mesh), m_use_floats (false), m_normals(0), m_vcolors(0), m_fcolors(0)
{ }
~Surface_mesh_filler()
{
for (std::size_t i = 0; i < m_vertex_properties.size(); ++ i)
delete m_vertex_properties[i];
for (std::size_t i = 0; i < m_face_properties.size(); ++ i)
delete m_face_properties[i];
for (std::size_t i = 0; i < m_edge_properties.size(); ++ i)
delete m_edge_properties[i];
for (std::size_t i = 0; i < m_halfedge_properties.size(); ++ i)
delete m_halfedge_properties[i];
}
bool has_simplex_specific_property (internal::PLY::PLY_read_number* property, Vertex_index)
{
const std::string& name = property->name();
if (name == "x" ||
name == "y" ||
name == "z")
{
if (dynamic_cast<PLY_read_typed_number<float>*>(property))
m_use_floats = true;
return true;
}
if (name == "nx" ||
name == "ny" ||
name == "nz")
{
++ m_normals;
if (m_normals == 3)
m_normal_map = m_mesh.template add_property_map<Vertex_index, Vector>("v:normal").first;
return true;
}
if (name == "red" ||
name == "green" ||
name == "blue")
{
++ m_vcolors;
if (m_vcolors == 3)
m_vcolor_map = m_mesh.template add_property_map<Vertex_index, CGAL::Color>("v:color").first;
return true;
}
return false;
}
bool has_simplex_specific_property (internal::PLY::PLY_read_number* property, Face_index)
{
const std::string& name = property->name();
if (name == "vertex_indices" || name == "vertex_index")
{
m_index_tag = name;
m_use_int32_t = dynamic_cast<PLY_read_typed_list<boost::int32_t>*>(property);
CGAL_assertion (dynamic_cast<PLY_read_typed_list<boost::uint32_t>*>(property));
return true;
}
if (name == "red" ||
name == "green" ||
name == "blue")
{
++ m_fcolors;
if (m_fcolors == 3)
m_fcolor_map = m_mesh.template add_property_map<Face_index, CGAL::Color>("f:color").first;
return true;
}
return false;
}
bool has_simplex_specific_property (internal::PLY::PLY_read_number* property, Edge_index)
{
const std::string& name = property->name();
if (name == "v0" || name == "v1")
return true;
return false;
}
bool has_simplex_specific_property (internal::PLY::PLY_read_number* property, Halfedge_index)
{
const std::string& name = property->name();
if (name == "source" || name == "target")
return true;
return false;
}
void instantiate_vertex_properties (PLY_element& element)
{
m_map_v2v.reserve(element.number_of_items());
instantiate_properties<Vertex_index> (element, m_vertex_properties);
}
void instantiate_face_properties (PLY_element& element)
{
instantiate_properties<Face_index> (element, m_face_properties);
}
void instantiate_edge_properties (PLY_element& element)
{
instantiate_properties<Edge_index> (element, m_edge_properties);
}
void instantiate_halfedge_properties (PLY_element& element)
{
instantiate_properties<Halfedge_index> (element, m_halfedge_properties);
}
template <typename Simplex>
void instantiate_properties (PLY_element& element,
std::vector<Abstract_ply_property_to_surface_mesh_property*>& properties)
{
for (std::size_t j = 0; j < element.number_of_properties(); ++ j)
{
internal::PLY::PLY_read_number* property = element.property(j);
if (has_simplex_specific_property (property, Simplex()))
continue;
const std::string& name = property->name();
if (dynamic_cast<PLY_read_typed_number<boost::int8_t>*>(property))
{
properties.push_back
(new PLY_property_to_surface_mesh_property<Simplex, boost::int8_t>(m_mesh,
name));
}
else if (dynamic_cast<PLY_read_typed_number<boost::uint8_t>*>(property))
{
properties.push_back
(new PLY_property_to_surface_mesh_property<Simplex, boost::uint8_t>(m_mesh,
name));
}
else if (dynamic_cast<PLY_read_typed_number<boost::int16_t>*>(property))
{
properties.push_back
(new PLY_property_to_surface_mesh_property<Simplex, boost::int16_t>(m_mesh,
name));
}
else if (dynamic_cast<PLY_read_typed_number<boost::uint16_t>*>(property))
{
properties.push_back
(new PLY_property_to_surface_mesh_property<Simplex, boost::uint16_t>(m_mesh,
name));
}
else if (dynamic_cast<PLY_read_typed_number<boost::int32_t>*>(property))
{
properties.push_back
(new PLY_property_to_surface_mesh_property<Simplex, boost::int32_t>(m_mesh,
name));
}
else if (dynamic_cast<PLY_read_typed_number<boost::uint32_t>*>(property))
{
properties.push_back
(new PLY_property_to_surface_mesh_property<Simplex, boost::uint32_t>(m_mesh,
name));
}
else if (dynamic_cast<PLY_read_typed_number<float>*>(property))
{
properties.push_back
(new PLY_property_to_surface_mesh_property<Simplex, float>(m_mesh,
name));
}
else if (dynamic_cast<PLY_read_typed_number<double>*>(property))
{
properties.push_back
(new PLY_property_to_surface_mesh_property<Simplex, double>(m_mesh,
name));
}
}
}
void process_vertex_line (PLY_element& element)
{
Vertex_index vi;
if (m_use_floats)
process_line<float>(element, vi);
else
process_line<double>(element, vi);
for (std::size_t i = 0; i < m_vertex_properties.size(); ++ i)
m_vertex_properties[i]->assign (element, vi);
}
template <typename FT>
void process_line (PLY_element& element, Vertex_index& vi)
{
FT x = (FT)0.,y = (FT)0., z = (FT)0.,
nx = (FT)0., ny = (FT)0., nz = (FT)0.;
element.assign (x, "x");
element.assign (y, "y");
element.assign (z, "z");
Point point (x, y, z);
vi = m_mesh.add_vertex(point);
m_map_v2v.push_back(vi);
if (m_normals == 3)
{
element.assign (nx, "nx");
element.assign (ny, "ny");
element.assign (nz, "nz");
Vector normal (nx, ny, nz);
m_normal_map[vi] = normal;
}
if (m_vcolors == 3)
{
unsigned char r, g, b;
element.assign (r, "red");
element.assign (g, "green");
element.assign (b, "blue");
m_vcolor_map[vi] = CGAL::Color (r, g, b);
}
}
bool process_face_line (PLY_element& element)
{
Face_index fi = m_mesh.null_face();
if (m_use_int32_t)
process_line<boost::int32_t>(element, fi);
else
process_line<boost::uint32_t>(element, fi);
if (fi == Surface_mesh::null_face())
return false;
for (std::size_t i = 0; i < m_face_properties.size(); ++ i)
m_face_properties[i]->assign (element, fi);
return true;
}
template <typename IntType>
void process_line (PLY_element& element, Face_index& fi)
{
std::vector<IntType> indices;
element.assign (indices, m_index_tag.c_str());
std::vector<Vertex_index> vertices;
vertices.reserve(indices.size());
for (std::size_t i = 0; i < indices.size(); ++ i)
vertices.push_back (m_map_v2v[std::size_t(indices[i])]);
fi = m_mesh.add_face(vertices);
if (fi == m_mesh.null_face())
return;
if (m_fcolors == 3)
{
unsigned char r, g, b;
element.assign (r, "red");
element.assign (g, "green");
element.assign (b, "blue");
m_fcolor_map[fi] = CGAL::Color (r, g, b);
}
}
bool process_edge_line (PLY_element& element)
{
Edge_index ei = m_mesh.null_edge();
if (m_use_int32_t)
process_line<boost::int32_t>(element, ei);
else
process_line<boost::uint32_t>(element, ei);
if (ei == Surface_mesh::null_edge())
return false;
for (std::size_t i = 0; i < m_edge_properties.size(); ++ i)
m_edge_properties[i]->assign (element, ei);
return true;
}
template <typename IntType>
void process_line (PLY_element& element, Edge_index& ei)
{
IntType v0, v1;
element.assign (v0, "v0");
element.assign (v1, "v1");
Halfedge_index hi = m_mesh.halfedge(m_map_v2v[std::size_t(v0)],
m_map_v2v[std::size_t(v1)]);
if (hi == m_mesh.null_halfedge())
return;
ei = m_mesh.edge (hi);
}
bool process_halfedge_line (PLY_element& element)
{
Halfedge_index hi = m_mesh.null_halfedge();
if (m_use_int32_t)
process_line<boost::int32_t>(element, hi);
else
process_line<boost::uint32_t>(element, hi);
if (hi == Surface_mesh::null_halfedge())
return false;
for (std::size_t i = 0; i < m_halfedge_properties.size(); ++ i)
m_halfedge_properties[i]->assign (element, hi);
return true;
}
template <typename IntType>
void process_line (PLY_element& element, Halfedge_index& hi)
{
IntType source, target;
element.assign (source, "source");
element.assign (target, "target");
hi = m_mesh.halfedge(m_map_v2v[std::size_t(source)], m_map_v2v[std::size_t(target)]);
}
};
template <typename Point>
bool fill_simplex_specific_header
(std::ostream& os, const Surface_mesh<Point>& sm,
std::vector<Abstract_property_printer<typename Surface_mesh<Point>::Vertex_index>*>& printers,
const std::string& prop)
{
typedef Surface_mesh<Point> SMesh;
typedef typename SMesh::Vertex_index VIndex;
typedef typename Kernel_traits<Point>::Kernel Kernel;
typedef typename Kernel::FT FT;
typedef typename Kernel::Vector_3 Vector;
typedef typename SMesh::template Property_map<VIndex, Point> Point_map;
typedef typename SMesh::template Property_map<VIndex, Vector> Vector_map;
typedef typename SMesh::template Property_map<VIndex, Color> Vcolor_map;
if (prop == "v:connectivity" ||
prop == "v:removed")
return true;
if (prop == "v:point")
{
if (boost::is_same<FT, float>::value)
{
os << "property float x" << std::endl
<< "property float y" << std::endl
<< "property float z" << std::endl;
}
else
{
os << "property double x" << std::endl
<< "property double y" << std::endl
<< "property double z" << std::endl;
}
printers.push_back (new Property_printer<VIndex,Point_map>(sm.points()));
return true;
}
bool okay = false;
if (prop == "v:normal")
{
Vector_map pmap;
boost::tie (pmap, okay) = sm.template property_map<VIndex,Vector>(prop);
if (okay)
{
if (boost::is_same<FT, float>::value)
{
os << "property float nx" << std::endl
<< "property float ny" << std::endl
<< "property float nz" << std::endl;
}
else
{
os << "property double nx" << std::endl
<< "property double ny" << std::endl
<< "property double nz" << std::endl;
}
printers.push_back (new Property_printer<VIndex,Vector_map>(pmap));
return true;
}
}
if (prop == "v:color")
{
Vcolor_map pmap;
boost::tie (pmap, okay) = sm.template property_map<VIndex,Color>(prop);
if (okay)
{
os << "property uchar red" << std::endl
<< "property uchar green" << std::endl
<< "property uchar blue" << std::endl
<< "property uchar alpha" << std::endl;
printers.push_back (new Property_printer<VIndex,Vcolor_map>(pmap));
return true;
}
}
return false;
}
template <typename Point>
bool fill_simplex_specific_header
(std::ostream& os, const Surface_mesh<Point>& sm,
std::vector<Abstract_property_printer<typename Surface_mesh<Point>::Face_index>*>& printers,
const std::string& prop)
{
typedef Surface_mesh<Point> SMesh;
typedef typename SMesh::Face_index FIndex;
typedef typename SMesh::template Property_map<FIndex, Color> Fcolor_map;
if (prop == "f:connectivity" ||
prop == "f:removed")
return true;
bool okay = false;
if (prop == "f:color")
{
Fcolor_map pmap;
boost::tie (pmap, okay) = sm.template property_map<FIndex,Color>(prop);
if (okay)
{
os << "property uchar red" << std::endl
<< "property uchar green" << std::endl
<< "property uchar blue" << std::endl
<< "property uchar alpha" << std::endl;
printers.push_back (new Property_printer<FIndex,Fcolor_map>(pmap));
return true;
}
}
return false;
}
template <typename Point>
bool fill_simplex_specific_header
(std::ostream& , const Surface_mesh<Point>& ,
std::vector<Abstract_property_printer<typename Surface_mesh<Point>::Edge_index>*>& ,
const std::string& prop)
{
if (prop == "e:removed")
return true;
return false;
}
template <typename Point>
bool fill_simplex_specific_header
(std::ostream& , const Surface_mesh<Point>& ,
std::vector<Abstract_property_printer<typename Surface_mesh<Point>::Halfedge_index>*>& ,
const std::string& prop)
{
if (prop == "h:connectivity")
return true;
return false;
}
template <typename Point>
std::string get_property_raw_name (const std::string& prop, typename Surface_mesh<Point>::Vertex_index)
{
std::string name = prop;
if (name.rfind("v:",0) == 0)
name = std::string (prop.begin() + 2, prop.end());
return name;
}
template <typename Point>
std::string get_property_raw_name (const std::string& prop, typename Surface_mesh<Point>::Face_index)
{
std::string name = prop;
if (name.rfind("f:",0) == 0)
name = std::string (prop.begin() + 2, prop.end());
return name;
}
template <typename Point>
std::string get_property_raw_name (const std::string& prop, typename Surface_mesh<Point>::Edge_index)
{
std::string name = prop;
if (name.rfind("e:",0) == 0)
name = std::string (prop.begin() + 2, prop.end());
return name;
}
template <typename Point>
std::string get_property_raw_name (const std::string& prop, typename Surface_mesh<Point>::Halfedge_index)
{
std::string name = prop;
if (name.rfind("h:",0) == 0)
name = std::string (prop.begin() + 2, prop.end());
return name;
}
template <typename Point, typename Simplex>
void fill_header (std::ostream& os, const Surface_mesh<Point>& sm,
std::vector<Abstract_property_printer<Simplex>*>& printers)
{
typedef Surface_mesh<Point> SMesh;
typedef typename SMesh::template Property_map<Simplex, boost::int8_t> Int8_map;
typedef typename SMesh::template Property_map<Simplex, boost::uint8_t> Uint8_map;
typedef typename SMesh::template Property_map<Simplex, boost::int16_t> Int16_map;
typedef typename SMesh::template Property_map<Simplex, boost::uint16_t> Uint16_map;
typedef typename SMesh::template Property_map<Simplex, boost::int32_t> Int32_map;
typedef typename SMesh::template Property_map<Simplex, boost::uint32_t> Uint32_map;
typedef typename SMesh::template Property_map<Simplex, boost::int64_t> Int64_map;
typedef typename SMesh::template Property_map<Simplex, boost::uint64_t> Uint64_map;
typedef typename SMesh::template Property_map<Simplex, float> Float_map;
typedef typename SMesh::template Property_map<Simplex, double> Double_map;
std::vector<std::string> prop = sm.template properties<Simplex>();
for (std::size_t i = 0; i < prop.size(); ++ i)
{
if (fill_simplex_specific_header(os, sm, printers, prop[i]))
continue;
// Cut the "v:" prefix
std::string name = get_property_raw_name<Point> (prop[i], Simplex());
bool okay = false;
{
Int8_map pmap;
boost::tie (pmap, okay) = sm.template property_map<Simplex,boost::int8_t>(prop[i]);
if (okay)
{
os << "property char " << name << std::endl;
printers.push_back (new internal::PLY::Char_property_printer<Simplex,Int8_map>(pmap));
continue;
}
}
{
Uint8_map pmap;
boost::tie (pmap, okay) = sm.template property_map<Simplex,boost::uint8_t>(prop[i]);
if (okay)
{
os << "property uchar " << name << std::endl;
printers.push_back (new internal::PLY::Char_property_printer<Simplex,Uint8_map>(pmap));
continue;
}
}
{
Int16_map pmap;
boost::tie (pmap, okay) = sm.template property_map<Simplex,boost::int16_t>(prop[i]);
if (okay)
{
os << "property short " << name << std::endl;
printers.push_back (new internal::PLY::Simple_property_printer<Simplex,Int16_map>(pmap));
continue;
}
}
{
Uint16_map pmap;
boost::tie (pmap, okay) = sm.template property_map<Simplex,boost::uint16_t>(prop[i]);
if (okay)
{
os << "property ushort " << name << std::endl;
printers.push_back (new internal::PLY::Simple_property_printer<Simplex,Uint16_map>(pmap));
continue;
}
}
{
Int32_map pmap;
boost::tie (pmap, okay) = sm.template property_map<Simplex,boost::int32_t>(prop[i]);
if (okay)
{
os << "property int " << name << std::endl;
printers.push_back (new internal::PLY::Simple_property_printer<Simplex,Int32_map>(pmap));
continue;
}
}
{
Uint32_map pmap;
boost::tie (pmap, okay) = sm.template property_map<Simplex,boost::uint32_t>(prop[i]);
if (okay)
{
os << "property uint " << name << std::endl;
printers.push_back (new internal::PLY::Simple_property_printer<Simplex,Uint32_map>(pmap));
continue;
}
}
{
Int64_map pmap;
boost::tie (pmap, okay) = sm.template property_map<Simplex,boost::int64_t>(prop[i]);
if (okay)
{
os << "property int " << name << std::endl;
printers.push_back (new internal::PLY::Simple_property_printer<Simplex,Int64_map,boost::int32_t>(pmap));
continue;
}
}
{
Uint64_map pmap;
boost::tie (pmap, okay) = sm.template property_map<Simplex,boost::uint64_t>(prop[i]);
if (okay)
{
os << "property uint " << name << std::endl;
printers.push_back (new internal::PLY::Simple_property_printer<Simplex,Uint64_map,boost::uint32_t>(pmap));
continue;
}
}
{
Float_map pmap;
boost::tie (pmap, okay) = sm.template property_map<Simplex,float>(prop[i]);
if (okay)
{
os << "property float " << name << std::endl;
printers.push_back (new internal::PLY::Simple_property_printer<Simplex,Float_map>(pmap));
continue;
}
}
{
Double_map pmap;
boost::tie (pmap, okay) = sm.template property_map<Simplex,double>(prop[i]);
if (okay)
{
os << "property double " << name << std::endl;
printers.push_back (new internal::PLY::Simple_property_printer<Simplex,Double_map>(pmap));
continue;
}
}
}
}
} // namespace PLY
#endif
} // namespace internal
} // namespace CGAL
#endif // CGAL_SURFACE_MESH_IO_PLY

View File

@ -53,6 +53,7 @@
#include <CGAL/boost/graph/iterator.h> #include <CGAL/boost/graph/iterator.h>
#include <CGAL/boost/graph/Euler_operations.h> #include <CGAL/boost/graph/Euler_operations.h>
#include <CGAL/IO/File_scanner_OFF.h> #include <CGAL/IO/File_scanner_OFF.h>
#include <CGAL/Surface_mesh/IO/PLY.h>
#include <CGAL/Handle_hash_function.h> #include <CGAL/Handle_hash_function.h>
#include <CGAL/boost/graph/named_params_helper.h> #include <CGAL/boost/graph/named_params_helper.h>
#include <CGAL/boost/graph/named_function_params.h> #include <CGAL/boost/graph/named_function_params.h>
@ -2160,6 +2161,204 @@ private: //------------------------------------------------------- private data
return os; return os;
} }
#if !defined(CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE) && !defined(CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES)
/// \relates Surface_mesh
/// Inserts the surface mesh in an output stream in PLY format.
/// If found, "v:normal", "v:color" and "f:color" are inserted in the stream.
/// All other vertex and face properties with simple types are inserted in the stream.
/// Edges are only inserted in the stream if they have at least one
/// property with simple type: if they do, all edge properties with
/// simple types are inserted in the stream. The halfedges follow
/// the same behavior.
///
/// If provided, the `comments` string is included line by line in
/// the header of the PLY stream (each line will be precedeed by
/// "comment ").
///
/// \relates Surface_mesh
template <typename P>
bool write_ply(std::ostream& os, const Surface_mesh<P>& sm, const std::string& comments = std::string())
{
typedef Surface_mesh<P> SMesh;
typedef typename Kernel_traits<P>::Kernel K;
typedef typename K::Vector_3 Vector;
typedef typename SMesh::Vertex_index VIndex;
typedef typename SMesh::Face_index FIndex;
typedef typename SMesh::Edge_index EIndex;
typedef typename SMesh::Halfedge_index HIndex;
typedef typename SMesh::template Property_map<FIndex, Color> Fcolor_map;
typedef typename SMesh::template Property_map<FIndex, boost::int8_t> Int8_map_f;
typedef typename SMesh::template Property_map<FIndex, boost::uint8_t> Uint8_map_f;
typedef typename SMesh::template Property_map<FIndex, boost::int16_t> Int16_map_f;
typedef typename SMesh::template Property_map<FIndex, boost::uint16_t> Uint16_map_f;
typedef typename SMesh::template Property_map<FIndex, boost::int32_t> Int32_map_f;
typedef typename SMesh::template Property_map<FIndex, boost::uint32_t> Uint32_map_f;
typedef typename SMesh::template Property_map<FIndex, boost::int64_t> Int64_map_f;
typedef typename SMesh::template Property_map<FIndex, boost::uint64_t> Uint64_map_f;
typedef typename SMesh::template Property_map<FIndex, float> Float_map_f;
typedef typename SMesh::template Property_map<FIndex, double> Double_map_f;
os << "ply" << std::endl
<< ((get_mode(os) == IO::BINARY) ? "format binary_little_endian 1.0" : "format ascii 1.0") << std::endl
<< "comment Generated by the CGAL library" << std::endl;
if (comments != std::string())
{
std::istringstream iss (comments);
std::string line;
while (getline(iss, line))
{
if (line != "Generated by the CGAL library") // Avoid repeating the line if multiple savings
os << "comment " << line << std::endl;
}
}
os << "element vertex " << sm.number_of_vertices() << std::endl;
std::vector<internal::PLY::Abstract_property_printer<VIndex>*> vprinters;
internal::PLY::fill_header (os, sm, vprinters);
os << "element face " << sm.number_of_faces() << std::endl;
os << "property list uchar int vertex_indices" << std::endl;
std::vector<internal::PLY::Abstract_property_printer<FIndex>*> fprinters;
internal::PLY::fill_header (os, sm, fprinters);
std::vector<internal::PLY::Abstract_property_printer<EIndex>*> eprinters;
if (sm.template properties<EIndex>().size() > 1)
{
os << "element edge " << sm.number_of_edges() << std::endl;
os << "property int v0" << std::endl;
os << "property int v1" << std::endl;
internal::PLY::fill_header (os, sm, eprinters);
}
std::vector<internal::PLY::Abstract_property_printer<HIndex>*> hprinters;
if (sm.template properties<HIndex>().size() > 1)
{
os << "element halfedge " << sm.number_of_halfedges() << std::endl;
os << "property int source" << std::endl;
os << "property int target" << std::endl;
internal::PLY::fill_header (os, sm, hprinters);
}
os << "end_header" << std::endl;
BOOST_FOREACH(VIndex vi, sm.vertices())
{
for (std::size_t i = 0; i < vprinters.size(); ++ i)
{
vprinters[i]->print(os, vi);
if (get_mode (os) == IO::ASCII)
os << " ";
}
if (get_mode (os) == IO::ASCII)
os << std::endl;
}
std::vector<VIndex> polygon;
BOOST_FOREACH(FIndex fi, sm.faces())
{
// Get list of vertex indices
polygon.clear();
BOOST_FOREACH(HIndex hi, halfedges_around_face(halfedge(fi, sm), sm))
polygon.push_back (sm.target(hi));
if (get_mode (os) == IO::ASCII)
{
os << polygon.size() << " ";
for (std::size_t i = 0; i < polygon.size(); ++ i)
os << int(polygon[i]) << " ";
}
else
{
unsigned char size = (unsigned char)(polygon.size());
os.write (reinterpret_cast<char*>(&size), sizeof(size));
for (std::size_t i = 0; i < polygon.size(); ++ i)
{
int idx = int(polygon[i]);
os.write (reinterpret_cast<char*>(&idx), sizeof(idx));
}
}
for (std::size_t i = 0; i < fprinters.size(); ++ i)
{
fprinters[i]->print(os, fi);
if (get_mode (os) == IO::ASCII)
os << " ";
}
if (get_mode (os) == IO::ASCII)
os << std::endl;
}
if (!eprinters.empty())
{
BOOST_FOREACH(EIndex ei, sm.edges())
{
if (get_mode (os) == IO::ASCII)
os << int(sm.vertex(ei,0)) << " " << int(sm.vertex(ei,1)) << " ";
else
{
int v0 = int(sm.vertex(ei,0));
int v1 = int(sm.vertex(ei,1));
os.write (reinterpret_cast<char*>(&v0), sizeof(v0));
os.write (reinterpret_cast<char*>(&v1), sizeof(v1));
}
for (std::size_t i = 0; i < eprinters.size(); ++ i)
{
eprinters[i]->print(os, ei);
if (get_mode (os) == IO::ASCII)
os << " ";
}
if (get_mode (os) == IO::ASCII)
os << std::endl;
}
}
if (!hprinters.empty())
{
BOOST_FOREACH(HIndex hi, sm.halfedges())
{
if (get_mode (os) == IO::ASCII)
os << int(sm.source(hi)) << " " << int(sm.target(hi)) << " ";
else
{
int source = int(sm.source(hi));
int target = int(sm.target(hi));
os.write (reinterpret_cast<char*>(&source), sizeof(source));
os.write (reinterpret_cast<char*>(&target), sizeof(target));
}
for (std::size_t i = 0; i < hprinters.size(); ++ i)
{
hprinters[i]->print(os, hi);
if (get_mode (os) == IO::ASCII)
os << " ";
}
if (get_mode (os) == IO::ASCII)
os << std::endl;
}
}
for (std::size_t i = 0; i < vprinters.size(); ++ i)
delete vprinters[i];
for (std::size_t i = 0; i < fprinters.size(); ++ i)
delete fprinters[i];
for (std::size_t i = 0; i < eprinters.size(); ++ i)
delete eprinters[i];
for (std::size_t i = 0; i < hprinters.size(); ++ i)
delete hprinters[i];
return true;
}
#endif
/// @cond CGAL_DOCUMENT_INTERNALS /// @cond CGAL_DOCUMENT_INTERNALS
@ -2218,7 +2417,7 @@ private: //------------------------------------------------------- private data
if(!is){ if(!is){
return false; return false;
} }
sm.reserve(sm.num_vertices()+n, sm.num_faces()+2*f, sm.num_edges()+e); sm.reserve(sm.num_vertices()+n, sm.num_edges()+e, sm.num_faces()+f);
std::vector<Vertex_index> vertexmap(n); std::vector<Vertex_index> vertexmap(n);
P p; P p;
Vector_3 v; Vector_3 v;
@ -2320,6 +2519,131 @@ private: //------------------------------------------------------- private data
return read_off(is, sm, parameters::all_default()); return read_off(is, sm, parameters::all_default());
} }
#if !defined(CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE) && !defined(CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES)
/// \cond SKIP_IN_MANUAL
template <typename P>
bool read_ply(std::istream& is, Surface_mesh<P>& sm)
{
std::string dummy;
return read_ply (is, sm, dummy);
}
/// \endcond
/// Extracts the surface mesh from an input stream in Ascii or
/// Binary PLY format and appends it to the surface mesh `sm`.
///
/// - the operator reads the vertex `point` property and the face
/// `vertex_index` (or `vertex_indices`) property;
/// - if three PLY properties `nx`, `ny` and `nz` with type `float`
/// or `double` are found for vertices, a "v:normal" vertex
/// property map is added;
/// - if three PLY properties `red`, `green` and `blue` with type
/// `uchar` are found for vertices, a "v:color" vertex property
/// map is added;
/// - if three PLY properties `red`, `green` and `blue` with type
/// `uchar` are found for faces, a "f:color" face property map is
/// added;
/// - if any other PLY property is found, a "[s]:[name]" property map is
/// added, where `[s]` is `v` for vertex and `f` for face, and
/// `[name]` is the name of the PLY property.
///
/// The `comments` parameter can be omitted. If provided, it will be
/// used to store the potential comments found in the PLY
/// header. Each line starting by "comment " in the header is
/// appended to the `comments` string (without the "comment " word).
///
/// \pre The data in the stream must represent a two-manifold. If this is not the case
/// the `failbit` of `is` is set and the mesh cleared.
/// \relates Surface_mesh
template <typename P>
bool read_ply(std::istream& is, Surface_mesh<P>& sm, std::string& comments)
{
if(!is)
{
std::cerr << "Error: cannot open file" << std::endl;
return false;
}
internal::PLY::PLY_reader reader;
internal::PLY::Surface_mesh_filler<P> filler(sm);
if (!(reader.init (is)))
{
is.setstate(std::ios::failbit);
return false;
}
comments = reader.comments();
for (std::size_t i = 0; i < reader.number_of_elements(); ++ i)
{
internal::PLY::PLY_element& element = reader.element(i);
bool is_vertex = (element.name() == "vertex" || element.name() == "vertices");
bool is_face = false;
bool is_edge = false;
bool is_halfedge = false;
if (is_vertex)
{
sm.reserve(sm.number_of_vertices() + element.number_of_items(),
sm.number_of_edges(),
sm.number_of_faces());
filler.instantiate_vertex_properties (element);
}
else
is_face = (element.name() == "face" || element.name() == "faces");
if (is_face)
{
sm.reserve(sm.number_of_vertices(),
sm.number_of_edges(),
sm.number_of_faces() + element.number_of_items());
filler.instantiate_face_properties (element);
}
else
is_edge = (element.name() == "edge");
if (is_edge)
filler.instantiate_edge_properties (element);
else
is_halfedge = (element.name() == "halfedge");
if (is_halfedge)
filler.instantiate_halfedge_properties (element);
for (std::size_t j = 0; j < element.number_of_items(); ++ j)
{
for (std::size_t k = 0; k < element.number_of_properties(); ++ k)
{
internal::PLY::PLY_read_number* property = element.property(k);
property->get (is);
if (is.fail())
return false;
}
if (is_vertex)
filler.process_vertex_line (element);
else if (is_face)
{
if (!filler.process_face_line (element))
{
is.setstate(std::ios::failbit);
return false;
}
}
else if (is_edge)
filler.process_edge_line (element);
else if (is_halfedge)
filler.process_halfedge_line (element);
}
}
return true;
}
#endif
/// \relates Surface_mesh /// \relates Surface_mesh
/// This operator calls `read_off(std::istream& is, CGAL::Surface_mesh& sm)`. /// This operator calls `read_off(std::istream& is, CGAL::Surface_mesh& sm)`.
/// \attention Up to %CGAL 4.10 this operator called `sm.clear()`. /// \attention Up to %CGAL 4.10 this operator called `sm.clear()`.

View File

@ -0,0 +1,38 @@
ply
format ascii 1.0
element vertex 4
property double x
property double y
property double z
property double nx
property double ny
property double nz
property uchar red
property uchar green
property uchar blue
property int id
element face 4
property list uchar int vertex_indices
property uchar red
property uchar green
property uchar blue
property int label
element edge 6
property int v0
property int v1
property float confidence
end_header
0 0 0 -0.5 -0.5 -0.5 255 255 0 0
0 0 1 -0.5 -0.5 0 0 255 255 1
0 1 0 -0.5 0 -0.5 128 0 255 2
1 0 0 0 -0.5 -0.5 255 128 0 3
3 0 1 2 255 0 0 -1
3 0 3 1 0 255 0 1
3 1 3 2 0 0 255 -1
3 0 2 3 255 0 255 0
0 1 0.1
0 2 0.2
0 3 0.3
1 2 0.4
1 3 0.5
2 3 0.6

View File

@ -0,0 +1,46 @@
#include <CGAL/Surface_mesh/Surface_mesh.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <cstring>
#include <iostream>
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::Point_3 Point;
typedef CGAL::Surface_mesh<Point> SMesh;
typedef boost::graph_traits<SMesh>::face_descriptor face_descriptor;
typedef boost::graph_traits<SMesh>::vertex_descriptor vertex_descriptor;
int main()
{
std::ifstream in ("colored_tetra.ply");
SMesh mesh;
CGAL::read_ply (in, mesh);
std::cerr << "Read mesh with " << mesh.number_of_vertices() << " vertices and "
<< mesh.number_of_faces() << " faces" << std::endl;
std::cerr << "Properties associated with vertices:" << std::endl;
std::vector<std::string> properties = mesh.properties<SMesh::Vertex_index>();
for (std::size_t i = 0; i < properties.size(); ++ i)
std::cerr << " * " << properties[i] << std::endl;
std::cerr << "Properties associated with faces:" << std::endl;
properties = mesh.properties<SMesh::Face_index>();
for (std::size_t i = 0; i < properties.size(); ++ i)
std::cerr << " * " << properties[i] << std::endl;
mesh.add_property_map<SMesh::Edge_index, short>("id", 42);
mesh.add_property_map<SMesh::Halfedge_index, float>("u", 13.f);
mesh.add_property_map<SMesh::Halfedge_index, float>("v", 37.f);
// Append second mesh
std::ifstream in2 ("tetra.ply");
CGAL::read_ply (in2, mesh);
std::ofstream out ("out.ply");
// CGAL::set_binary_mode(out);
CGAL::write_ply (out, mesh);
return 0;
}

View File

@ -0,0 +1,14 @@
ply
format ascii 1.0
element vertex 3
property double x
property double y
property double z
property int blabla
element face 1
property list uchar int vertex_indices
end_header
0 0 2 1000
0 1 2 200
1 0 2 30
3 0 1 2

View File

@ -22,11 +22,11 @@ int main() {
t.insert(Point(2,2)); t.insert(Point(2,2));
Finite_faces_iterator fc = t.finite_faces_begin(); Finite_faces_iterator fc = t.finite_faces_begin();
for( ; fc != t.finite_faces_end(); ++fc) fc->info() = CGAL::BLUE; for( ; fc != t.finite_faces_end(); ++fc) fc->info() = CGAL::blue();
Point p(0.5,0.5); Point p(0.5,0.5);
Face_handle fh = t.locate(p); Face_handle fh = t.locate(p);
fh->info() = CGAL::RED; fh->info() = CGAL::red();
return 0; return 0;
} }

View File

@ -66,7 +66,7 @@ int main()
Delaunay::Finite_vertices_iterator vit; Delaunay::Finite_vertices_iterator vit;
for (vit = T.finite_vertices_begin(); vit != T.finite_vertices_end(); ++vit) for (vit = T.finite_vertices_begin(); vit != T.finite_vertices_end(); ++vit)
if (T.degree(vit) == 6) if (T.degree(vit) == 6)
vit->info() = CGAL::RED; vit->info() = CGAL::red();
std::cout << " Visualization of T" << std::endl; std::cout << " Visualization of T" << std::endl;
gv.set_wired(true); gv.set_wired(true);

View File

@ -136,7 +136,7 @@ int main()
std::cout <<" Locating point (1,1,1) :" << std::endl; std::cout <<" Locating point (1,1,1) :" << std::endl;
Point p(1,1,1); Point p(1,1,1);
gv.set_vertex_color(CGAL::ORANGE); gv.set_vertex_color(CGAL::orange());
gv << p; gv << p;
Locate_type lt; Locate_type lt;
int li, lj; int li, lj;
@ -144,7 +144,7 @@ int main()
sleep(3); sleep(3);
gv << CGAL::VIOLET; gv << CGAL::violet();
if ( lt == Triangulation::CELL ) { if ( lt == Triangulation::CELL ) {
std::cout <<" CELL" << std::endl; std::cout <<" CELL" << std::endl;
visu_cell(gv,T,c); visu_cell(gv,T,c);

View File

@ -74,7 +74,7 @@ int main()
gv << T; gv << T;
std::cout <<" Visualizing the Voronoi edges" << std::endl; std::cout <<" Visualizing the Voronoi edges" << std::endl;
gv << CGAL::RED; gv << CGAL::red();
T.draw_dual(gv); T.draw_dual(gv);
char ch; char ch;

View File

@ -30,7 +30,7 @@ int main()
Delaunay::Finite_vertices_iterator vit; Delaunay::Finite_vertices_iterator vit;
for (vit = T.finite_vertices_begin(); vit != T.finite_vertices_end(); ++vit) for (vit = T.finite_vertices_begin(); vit != T.finite_vertices_end(); ++vit)
if (T.degree(vit) == 6) if (T.degree(vit) == 6)
vit->info() = CGAL::RED; vit->info() = CGAL::red();
return 0; return 0;
} }