dust3d/thirdparty/cgal/CGAL-4.13/include/CGAL/IO/Geomview_stream.h

607 lines
16 KiB
C
Raw Normal View History

// Copyright (c) 1997,1998,1999,2000,2001
// 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, Sylvain Pion
#ifndef CGAL_GEOMVIEW_STREAM_H
#define CGAL_GEOMVIEW_STREAM_H
#include <CGAL/basic.h>
#ifdef CGAL_USE_GEOMVIEW
#include <CGAL/Bbox_2.h>
#include <CGAL/Bbox_3.h>
#include <CGAL/IO/Color.h>
#include <CGAL/IO/Ostream_iterator.h>
#include <CGAL/export/CGAL.h>
#include <map>
#include <vector>
#include <utility>
#include <string>
#include <iterator>
#include <algorithm>
namespace CGAL {
class CGAL_EXPORT Geomview_stream {
public:
Geomview_stream(const Bbox_3 &bbox = Bbox_3(0,0,0, 1,1,1),
const char *machine = NULL,
const char *login = NULL);
~Geomview_stream();
Geomview_stream &operator<<(const Color &c);
Geomview_stream &operator<<(const std::string & s);
Geomview_stream &operator<<(int i);
Geomview_stream &operator<<(unsigned int i);
Geomview_stream &operator<<(long i);
Geomview_stream &operator<<(unsigned long i);
Geomview_stream &operator<<(double d);
template < class InputIterator >
void
draw_triangles(InputIterator begin, InputIterator end);
Geomview_stream &operator>>(char *expr);
void clear();
void look_recenter();
void set_bg_color(const Color &c);
Color get_vertex_color() const;
Color get_edge_color() const;
Color get_face_color() const;
Color set_vertex_color(const Color&);
Color set_edge_color(const Color&);
Color set_face_color(const Color&);
double vcr() const;
double vcg() const;
double vcb() const;
double ecr() const;
double ecg() const;
double ecb() const;
double fcr() const;
double fcg() const;
double fcb() const;
double get_vertex_radius() const
{
return radius;
}
double set_vertex_radius(double r)
{
std::swap(r, radius);
return r;
}
int get_line_width() const
{
return line_width;
}
int set_line_width(int w)
{
std::swap(w, line_width);
return w;
}
bool set_wired(bool b)
{
std::swap(b, wired_flag);
return b;
}
bool get_wired() const
{
return wired_flag;
}
bool set_echo(bool b)
{
std::swap(b, echo_flag);
return b;
}
bool get_echo() const
{
return echo_flag;
}
bool set_raw(bool b)
{
std::swap(b, raw_flag);
return b;
}
bool get_raw() const
{
return raw_flag;
}
bool set_trace(bool b)
{
std::swap(b, trace_flag);
return b;
}
bool get_trace() const
{
return trace_flag;
}
void trace(const std::string s) const
{
if (get_trace())
std::cerr << s;
}
void trace(double d) const
{
if (get_trace())
std::cerr << d << ' ';
}
void trace(int i) const
{
if (get_trace())
std::cerr << i << ' ';
}
void trace(unsigned int i) const
{
if (get_trace())
std::cerr << i << ' ';
}
bool set_binary_mode(bool b = true)
{
std::swap(b, binary_flag);
return b;
}
bool set_ascii_mode(bool b = true)
{
return !set_binary_mode(!b);
}
bool get_binary_mode() const
{
return binary_flag;
}
bool get_ascii_mode() const
{
return !binary_flag;
}
std::string get_new_id(const std::string & s);
const Bbox_3 & get_bbox()
{
return bb;
}
void pickplane()
{
pickplane(get_bbox());
}
static char* nth(char* s, int count);
static void parse_point(const char* pickpoint,
double &x, double &y, double &z, double &w);
private:
void setup_geomview(const char *machine, const char *login);
void frame(const Bbox_3 &bbox);
void pickplane(const Bbox_3 &bbox);
Bbox_3 bb;
Color vertex_color, edge_color, face_color;
bool wired_flag; // decides if we draw surfaces or edges.
bool echo_flag; // decides if we echo the point we get back to Geomview.
bool raw_flag; // decides if we output footers and headers.
bool trace_flag; // makes operator<<() write a trace on cerr.
bool binary_flag; // makes operator<<() write binary format
int line_width; // width of edges
double radius; // radius of vertices
int in, out; // file descriptors for input and output pipes
int pid; // the geomview process identification
std::map<std::string, int> id; // used to get a unique ID per type.
};
// Factorize code for Point_2 and Point_3.
template < class FT >
void
output_point(Geomview_stream &gv, const FT &x, const FT &y, const FT &z)
{
bool ascii_bak = true; // the initialization value shuts up the compiler.
if (!gv.get_raw()) {
ascii_bak = gv.set_ascii_mode();
gv << "(geometry " << gv.get_new_id("P")
<< " {appearance {linewidth 5 material {edgecolor "
<< gv.vcr() << gv.vcg() << gv.vcb() << "}}{SKEL 1 1 ";
}
gv << CGAL::to_double(x) << CGAL::to_double(y) << CGAL::to_double(z);
if (!gv.get_raw()) {
gv << "1 0\n}})";
gv.set_ascii_mode(ascii_bak);
}
}
#if defined CGAL_POINT_2_H && \
!defined CGAL_GV_OUT_POINT_2_H
#define CGAL_GV_OUT_POINT_2_H
template < class R >
Geomview_stream&
operator<<(Geomview_stream &gv, const Point_2<R> &p)
{
typename R::FT zero(0);
output_point(gv, p.x(), p.y(), zero);
return gv;
}
#endif
#if defined CGAL_POINT_3_H && \
!defined CGAL_GV_OUT_POINT_3_H
#define CGAL_GV_OUT_POINT_3_H
template < class R >
Geomview_stream&
operator<<(Geomview_stream &gv, const Point_3<R> &p)
{
output_point(gv, p.x(), p.y(), p.z());
return gv;
}
#endif
// The following code is the same for Segment_2 and Segment_3.
template < class Segment >
void
output_segment(Geomview_stream &gv, const Segment &segment)
{
bool ascii_bak = gv.set_ascii_mode();
gv << "(geometry " << gv.get_new_id("Seg")
<< " {appearance {linewidth "
<< gv.get_line_width() << "}{VECT "
<< 1 << 2 << 1 // 1 polyline, two vertices, 1 color
<< 2 // the first polyline contains 2 vertices
<< 1; // and it has 1 color
// here are start and end points
bool raw_bak = gv.set_raw(true);
gv << segment.source() << segment.target();
gv.set_raw(raw_bak);
// and the color of the segment and its opaqueness
gv << gv.ecr() << gv.ecg() << gv.ecb() << 1.0 << "}})";
gv.set_ascii_mode(ascii_bak);
}
#if defined CGAL_SEGMENT_2_H && \
!defined CGAL_GV_OUT_SEGMENT_2_H
#define CGAL_GV_OUT_SEGMENT_2_H
template < class R >
Geomview_stream&
operator<<(Geomview_stream &gv, const Segment_2<R> &segment)
{
output_segment(gv, segment);
return gv;
}
#endif
#if defined CGAL_SEGMENT_3_H && \
!defined CGAL_GV_OUT_SEGMENT_3_H
#define CGAL_GV_OUT_SEGMENT_3_H
template < class R >
Geomview_stream&
operator<<(Geomview_stream &gv, const Segment_3<R> &segment)
{
output_segment(gv, segment);
return gv;
}
#endif
// The following code is the same for Triangle_2 and Triangle_3.
template < class Triangle >
void
output_triangle(Geomview_stream &gv, const Triangle &triangle)
{
bool ascii_bak = gv.set_ascii_mode();
gv << "(geometry " << gv.get_new_id("Tr")
<< " {appearance {+edge material {edgecolor "
<< gv.ecr() << gv.ecg() << gv.ecb() << " } shading constant}{ ";
gv.set_binary_mode();
// it's a planar polygon
gv << "OFF BINARY\n"
// it has 3 vertices, 1 face and 3 edges
<< 3 << 1 << 3;
bool raw_bak = gv.set_raw(true);
for(int i=0; i<3; i++)
gv << triangle[i];
gv.set_raw(raw_bak);
// the face
gv << 3 << 0 << 1 << 2 << 4 << gv.fcr() << gv.fcg() << gv.fcb() << 1.0
<< "}})";
gv.set_ascii_mode(ascii_bak);
}
// Draws a set of triangles as OFF format (it's faster than one by one).
template < class InputIterator >
void
Geomview_stream::draw_triangles(InputIterator begin, InputIterator end)
{
typedef typename std::iterator_traits<InputIterator>::value_type Triangle;
typedef typename Kernel_traits<Triangle>::Kernel Kernel;
typedef typename Kernel::Point_3 Point;
typedef typename Kernel::Less_xyz_3 Comp;
// We first copy everything in a vector to only require an InputIterator.
std::vector<Triangle> triangles(begin, end);
typedef typename std::vector<Triangle>::const_iterator Tit;
// Put the points in a map and a vector.
// The index of a point in the vector is the value associated
// to it in the map.
typedef std::map<Point, int, Comp> Point_map;
Point_map point_map(Kernel().less_xyz_3_object());
std::vector<Point> points;
for (Tit i = triangles.begin(); i != triangles.end(); ++i)
for (int j = 0; j < 3; ++j)
if (point_map.insert(typename Point_map::value_type(i->vertex(j),
points.size())).second)
points.push_back(i->vertex(j));
bool ascii_bak = get_ascii_mode();
bool raw_bak = set_raw(true);
// Header.
set_binary_mode();
(*this) << "(geometry " << get_new_id("triangles")
<< " {appearance {}{ OFF BINARY\n"
<< points.size() << triangles.size() << 0;
// Points coordinates.
std::copy(points.begin(), points.end(),
Ostream_iterator<Point, Geomview_stream>(*this));
// Triangles vertices indices.
for (Tit tit = triangles.begin(); tit != triangles.end(); ++tit) {
(*this) << 3;
for (int j = 0; j < 3; ++j)
(*this) << point_map[tit->vertex(j)];
(*this) << 0; // without color.
}
// Footer.
(*this) << "}})";
set_raw(raw_bak);
set_ascii_mode(ascii_bak);
}
#if defined CGAL_TRIANGLE_2_H && \
!defined CGAL_GV_OUT_TRIANGLE_2_H
#define CGAL_GV_OUT_TRIANGLE_2_H
template < class R >
Geomview_stream&
operator<<(Geomview_stream &gv, const Triangle_2<R> &triangle)
{
output_triangle(gv, triangle);
return gv;
}
#endif
#if defined CGAL_TRIANGLE_3_H && \
!defined CGAL_GV_OUT_TRIANGLE_3_H
#define CGAL_GV_OUT_TRIANGLE_3_H
template < class R >
Geomview_stream&
operator<<(Geomview_stream &gv, const Triangle_3<R> &triangle)
{
output_triangle(gv, triangle);
return gv;
}
#endif
#if defined CGAL_TETRAHEDRON_3_H && \
!defined CGAL_GV_OUT_TETRAHEDRON_3_H
#define CGAL_GV_OUT_TETRAHEDRON_3_H
template < class R >
Geomview_stream&
operator<<(Geomview_stream &gv, const Tetrahedron_3<R> &t)
{
bool ascii_bak = gv.set_ascii_mode();
gv << "(geometry " << gv.get_new_id("Tetra")
<< " {appearance {}{ ";
gv.set_binary_mode();
gv << "OFF BINARY\n"
// it has 4 vertices, 4 face and 6 edges
<< 4 << 4 << 6 ;
// the vertices
bool raw_bak = gv.set_raw(true);
for(int i=0; i<4; i++)
gv << t[i];
gv.set_raw(raw_bak);
// the faces
double r = gv.fcr(),
g = gv.fcg(),
b = gv.fcb();
gv << 3 << 0 << 1 << 2 << 4 << r << g << b << 1.0
<< 3 << 3 << 0 << 1 << 4 << r << g << b << 1.0
<< 3 << 3 << 1 << 2 << 4 << r << g << b << 1.0
<< 3 << 3 << 0 << 2 << 4 << r << g << b << 1.0
<< "}})";
gv.set_ascii_mode(ascii_bak);
return gv;
}
#endif
#if defined CGAL_SPHERE_3_H && \
!defined CGAL_GV_OUT_SPHERE_3_H
#define CGAL_GV_OUT_SPHERE_3_H
template < class R >
Geomview_stream&
operator<<(Geomview_stream &gv, const Sphere_3<R> &S)
{
bool ascii_bak = gv.set_ascii_mode();
gv << "(geometry " << gv.get_new_id("Sph")
<< " {appearance {+edge material {edgecolor "
<< gv.ecr() << gv.ecg() << gv.ecb() << "} shading constant}{ "
<< "SPHERE\n"
<< std::sqrt(CGAL::to_double(S.squared_radius())) << "\n";
bool raw_bak = gv.set_raw(true);
gv << Point_3<R>(S.center()) << "}})";
gv.set_raw(raw_bak);
gv.set_ascii_mode(ascii_bak);
return gv;
}
#endif
#if defined CGAL_RAY_2_H && \
!defined CGAL_GV_OUT_RAY_2_H
#define CGAL_GV_OUT_RAY_2_H
template < class R >
Geomview_stream&
operator<<(Geomview_stream &gv, const Ray_2<R> &r)
{
// Note: it won't work if double is not convertible to an RT...
const Bbox_3 & bb = gv.get_bbox();
Object result = intersection(Iso_rectangle_2<R>(
Point_2<R>(bb.xmin(), bb.ymin()),
Point_2<R>(bb.xmax(), bb.ymax())), r);
Point_2<R> ipoint;
Segment_2<R> iseg;
if (assign(ipoint, result))
gv << ipoint;
else if (assign(iseg, result))
gv << iseg;
return gv;
}
#endif
#if defined CGAL_LINE_2_H && \
!defined CGAL_GV_OUT_LINE_2_H
#define CGAL_GV_OUT_LINE_2_H
template < class R >
Geomview_stream&
operator<<(Geomview_stream &gv, const Line_2<R> &r)
{
// Note: it won't work if double is not convertible to an RT...
const Bbox_3 & bb = gv.get_bbox();
Object result = intersection(Iso_rectangle_2<R>(
Point_2<R>(bb.xmin(), bb.ymin()),
Point_2<R>(bb.xmax(), bb.ymax())), r);
Point_2<R> ipoint;
Segment_2<R> iseg;
if (assign(ipoint, result))
gv << ipoint;
else if (assign(iseg, result))
gv << iseg;
return gv;
}
#endif
// Ray and Line drawing should be done by intersecting them with the BBox
// of the Geomview_stream. But for now we take the easy approach.
#if defined CGAL_RAY_3_H && \
!defined CGAL_GV_OUT_RAY_3_H
#define CGAL_GV_OUT_RAY_3_H
template < class R >
Geomview_stream&
operator<<(Geomview_stream &gv, const Ray_3<R> &r)
{
typename R::Segment_3 s(r.source(), r.point(1));
gv << s;
return gv;
}
#endif
#if defined CGAL_LINE_3_H && \
!defined CGAL_GV_OUT_LINE_3_H
#define CGAL_GV_OUT_LINE_3_H
template < class R >
Geomview_stream&
operator<<(Geomview_stream &gv, const Line_3<R> &r)
{
typename R::Segment_3 s(r.point(-1), r.point(1));
gv << s;
return gv;
}
#endif
CGAL_EXPORT Geomview_stream&
operator<<(Geomview_stream &gv, const Bbox_2 &bbox);
CGAL_EXPORT Geomview_stream&
operator<<(Geomview_stream &gv, const Bbox_3 &bbox);
#if defined CGAL_POINT_3_H && !defined CGAL_GV_IN_POINT_3_H
#define CGAL_GV_IN_POINT_3_H
template < class R >
Geomview_stream&
operator>>(Geomview_stream &gv, Point_3<R> &point)
{
const char *gclpick =
"(pick world pickplane * nil nil nil nil nil nil nil)";
bool ascii_bak = gv.set_ascii_mode();
gv << "(pickable pickplane yes) (ui-target pickplane yes)"
<< "(interest " << gclpick << ")";
char sexpr[1024];
gv >> sexpr; // this reads a gcl expression
const char* pickpoint = Geomview_stream::nth(sexpr, 3);
// this gives something as: (0.0607123 0.0607125 4.76837e-07 0.529628)
double x, y, z, w;
Geomview_stream::parse_point(pickpoint, x, y, z, w);
point = Point_3<R>(x, y, z, w);
// we echo the input
if (gv.get_echo())
gv << point;
// we are done and tell geomview to stop sending pick events
gv << "(uninterest " << gclpick << ") (pickable pickplane no)";
gv.set_ascii_mode(ascii_bak);
return gv;
}
#endif
} //namespace CGAL
#ifdef CGAL_HEADER_ONLY
#include <CGAL/IO/Geomview_stream_impl.h>
#endif // CGAL_HEADER_ONLY
#endif // CGAL_USE_GEOMVIEW
#endif // CGAL_GEOMVIEW_STREAM_H