Merge pull request #127 from gdamiand/Combinatorial_map_save_load-gdamiand

Combinatorial_map: add save/load functionality in the LCC demo
This commit is contained in:
Laurent Rineau 2015-09-03 13:43:36 +02:00
commit 69706c7de9
10 changed files with 2145 additions and 751 deletions

View File

@ -22,7 +22,6 @@
#include <CGAL/Compact_container.h>
#include <CGAL/internal/Combinatorial_map_utility.h>
#include <CGAL/internal/Combinatorial_map_internal_functors.h>
#include <CGAL/internal/Combinatorial_map_group_functors.h>
#include <CGAL/internal/Combinatorial_map_copy_functors.h>
#include <CGAL/internal/Combinatorial_map_sewable.h>
@ -350,6 +349,18 @@ namespace CGAL {
bool is_empty() const
{ return mdarts.empty(); }
friend std::ostream& operator<< (std::ostream& os, const Self& amap)
{
save_combinatorial_map(amap, os);
return os;
}
friend std::ifstream& operator>> (std::ifstream& is, Self& amap)
{
load_combinatorial_map(is, amap);
return is;
}
/** Create a new dart and add it to the map.
* The marks of the darts are initialised with mmask_marks, i.e. the dart
* is unmarked for all the marks.

View File

@ -0,0 +1,800 @@
// Copyright (c) 2010-2011 CNRS and LIRIS' Establishments (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 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$
//
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
// Guillaume Castano <guillaume.castano@gmail.com>
// Pascal Khieu <pascal.khieu@gmail.com>
//
#ifndef CGAL_COMBINATORIAL_MAP_SAVE_LOAD_H
#define CGAL_COMBINATORIAL_MAP_SAVE_LOAD_H
#include <boost/foreach.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/lexical_cast.hpp>
#include <CGAL/Combinatorial_map.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Cell_attribute_with_point.h>
#include <algorithm>
#include <map>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <typeinfo>
namespace CGAL {
typedef Exact_predicates_inexact_constructions_kernel::Point_3 RPoint_3;
typedef Exact_predicates_exact_constructions_kernel::Point_3 EPoint_3;
// Tags used in xml tree:
// For darts:
// <darts>
// <d> // new dart
// <b i="1"> neighbor dart index for beta1 </b>
// ...
// <v> value of dart (optional) </v>
// </d>
// ...
// </darts>
// For attributes:
// <attributes>
// <dimension index="1"> // new type of non void attribute
// <type>type of the info associated</type>
// <a> // new attribute
// <d> dart index </d>
// <v> value of attribute </v>
// </a>
// ...
// </attributes>
// Here T is a Dart_const_handle so we don't need &
template<typename T>
void write_cmap_dart_node(boost::property_tree::ptree & /*node*/, T)
{}
template<typename T>
void write_cmap_attribute_node(boost::property_tree::ptree & /*node*/, const T&)
{}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
char val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
unsigned char val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
short int val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
unsigned short int val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
int val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
unsigned int val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
long int val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
unsigned long int val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
float val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
double val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
long double val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
bool val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
const std::string& val)
{node.add("v",val);}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
const RPoint_3& val)
{
node.add("p.x",val.x());
node.add("p.y",val.y());
node.add("p.z",val.z());
}
inline
void write_cmap_attribute_node(boost::property_tree::ptree & node,
const EPoint_3& val)
{
node.add("p.x",CGAL::to_double(val.x()));
node.add("p.y",CGAL::to_double(val.y()));
node.add("p.z",CGAL::to_double(val.z()));
}
template<typename CMap, unsigned int i,
bool WithInfo=CGAL::Is_attribute_has_non_void_info
<typename CMap::template Attribute_type<i>::type>::value,
bool WithPoint=CGAL::Is_attribute_has_point
<typename CMap::template Attribute_type<i>::type >::value >
struct My_functor_cmap_save_one_attrib;
// An attrib with point and with info
template<typename CMap, unsigned int i>
struct My_functor_cmap_save_one_attrib<CMap, i, true, true>
{
static void run(const CMap* amap, boost::property_tree::ptree* ptree,
std::map<typename CMap::Dart_const_handle, typename CMap::size_type>* myDarts)
{
// to check all i-cells of the map
typename CMap::template Attribute_range<i>::type::const_iterator
it_attrib, itend_attrib;
it_attrib=amap->template attributes<i>().begin();
itend_attrib=amap->template attributes<i>().end();
// add dimension & type
boost::property_tree::ptree & ndim = ptree->add("dimension", "");
ndim.put("<xmlattr>.index", i);
ndim.add("type", typeid(typename CMap::template Attribute_type<i>::type::Info).name());
ndim.add("type_point", typeid(RPoint_3).name());
// for every attribute of the dimension
for (; it_attrib!=itend_attrib; ++it_attrib)
{
// make composant, dart and property node
boost::property_tree::ptree & nattr = ndim.add("a", "");
/* boost::property_tree::ptree & ndarts = */
nattr.add("d", (*myDarts)[it_attrib->dart()]);
// update property node to add a value node (from basic or custom type
write_cmap_attribute_node(nattr, it_attrib->info());
write_cmap_attribute_node(nattr, it_attrib->point());
}
}
};
// An attribute with point and without info
template<typename CMap, unsigned int i>
struct My_functor_cmap_save_one_attrib<CMap, i, false, true>
{
static void run(const CMap* amap, boost::property_tree::ptree* ptree,
std::map<typename CMap::Dart_const_handle, typename CMap::size_type>* myDarts)
{
// to check all i-cells of the map
typename CMap::template Attribute_range<i>::type::const_iterator
it_attrib, itend_attrib;
it_attrib=amap->template attributes<i>().begin();
itend_attrib=amap->template attributes<i>().end();
// add dimension & type
boost::property_tree::ptree & ndim = ptree->add("dimension", "");
ndim.put("<xmlattr>.index", i);
ndim.add("type", "void");
ndim.add("type_point", typeid(RPoint_3).name());
// for every attribute of the dimension
for (; it_attrib!=itend_attrib; ++it_attrib)
{
// make composant, dart and property node
boost::property_tree::ptree & nattr = ndim.add("a", "");
/* boost::property_tree::ptree & ndarts = */
nattr.add("d", (*myDarts)[it_attrib->dart()]);
// update property node to add a value node (from basic or custom type
write_cmap_attribute_node(nattr, it_attrib->point());
}
}
};
// An attribute without point and with info
template<typename CMap, unsigned int i>
struct My_functor_cmap_save_one_attrib<CMap, i, true, false>
{
static void run(const CMap* amap, boost::property_tree::ptree* ptree,
std::map<typename CMap::Dart_const_handle, typename CMap::size_type>* myDarts)
{
// to check all i-cells of the map
typename CMap::template Attribute_range<i>::type::const_iterator
it_attrib, itend_attrib;
it_attrib=amap->template attributes<i>().begin();
itend_attrib=amap->template attributes<i>().end();
// add dimension & type
boost::property_tree::ptree & ndim = ptree->add("dimension", "");
ndim.put("<xmlattr>.index", i);
ndim.add("type", typeid(typename CMap::template Attribute_type<i>::type::Info).name());
ndim.add("type_point", "void");
// for every attribute of the dimension
for (; it_attrib!=itend_attrib; ++it_attrib)
{
// make composant, dart and property node
boost::property_tree::ptree & nattr = ndim.add("a", "");
/* boost::property_tree::ptree & ndarts = */
nattr.add("d", (*myDarts)[it_attrib->dart()]);
// update property node to add a value node (from basic or custom type
write_cmap_attribute_node(nattr, it_attrib->info());
}
}
};
// An attrib without point and without info
template<typename CMap, unsigned int i>
struct My_functor_cmap_save_one_attrib<CMap, i, false, false>
{
static void run(const CMap* amap, boost::property_tree::ptree* ptree,
std::map<typename CMap::Dart_const_handle, typename CMap::size_type>* myDarts)
{
// to check all i-cells of the map
typename CMap::template Attribute_range<i>::type::const_iterator
it_attrib, itend_attrib;
it_attrib=amap->template attributes<i>().begin();
itend_attrib=amap->template attributes<i>().end();
// add dimension & type
boost::property_tree::ptree & ndim = ptree->add("dimension", "");
ndim.put("<xmlattr>.index", i);
ndim.add("type", "void");
ndim.add("type_point", "void");
// for every attribute of the dimension
for (; it_attrib!=itend_attrib; ++it_attrib)
{
// make composant, dart and property node
boost::property_tree::ptree & nattr = ndim.add("a", "");
/* boost::property_tree::ptree & ndarts = */
nattr.add("d", (*myDarts)[it_attrib->dart()]);
}
}
};
template<typename CMap>
struct My_functor_cmap_save_attrib
{
template <unsigned int i>
static void run(const CMap* amap, boost::property_tree::ptree* ptree,
std::map<typename CMap::Dart_const_handle, typename CMap::size_type>* myDarts)
{
My_functor_cmap_save_one_attrib<CMap, i>::run(amap, ptree, myDarts);
}
};
template < class CMap >
boost::property_tree::ptree cmap_save_darts
(const CMap& amap, std::map<typename CMap::Dart_const_handle, typename CMap::size_type>& myDarts)
{
assert( myDarts.empty() );
// First we numbered each dart by using the std::map.
typename CMap::Dart_range::const_iterator it(amap.darts().begin());
for(typename CMap::size_type num=1; num<=amap.number_of_darts();
++num, ++it)
{
myDarts[it] = num;
}
// make a tree
using boost::property_tree::ptree;
ptree pt;
// Now we save each dart, and its neighbors.
it=amap.darts().begin();
for(typename CMap::size_type num=0; num<amap.number_of_darts(); ++num, ++it)
{
// make a dart node
ptree & ndart = pt.add("d", "");
// the beta, only for non free sews
for(unsigned int dim=1; dim<=amap.dimension; dim++)
{
if(!amap.is_free(it, dim))
{
ptree & currentNext = ndart.add("b", myDarts[amap.beta(it, dim)]);
currentNext.put("<xmlattr>.i", dim);
}
}
// update property node to add a value node (if user defined its own
// function)
write_cmap_dart_node(ndart, it);
}
return pt;
}
template < class CMap >
boost::property_tree::ptree cmap_save_attributes
(const CMap& amap, std::map<typename CMap::Dart_const_handle, typename CMap::size_type>& myDarts)
{
using boost::property_tree::ptree;
ptree pt;
// update pt adding nodes containing attributes informations
CMap::Helper::template Foreach_enabled_attributes
<My_functor_cmap_save_attrib<CMap> >::run(&amap, &pt, &myDarts);
return pt;
}
template < class CMap >
bool save_combinatorial_map(const CMap& amap, std::ostream & output)
{
using boost::property_tree::ptree;
ptree data;
// map dart => number
std::map<typename CMap::Dart_const_handle, typename CMap::size_type> myDarts;
// Get darts
ptree pt_darts;
pt_darts = cmap_save_darts(amap, myDarts);
data.add_child("data.darts",pt_darts);
// Get attributes
ptree pt_attr;
pt_attr = cmap_save_attributes(amap, myDarts);
data.add_child("data.attributes", pt_attr);
// save data in output
write_xml(output, data);
return true;
}
template < class CMap >
bool save_combinatorial_map(const CMap& amap, const char* filename)
{
std::ofstream output(filename);
if (!output) return false;
return save_combinatorial_map(amap, output);
}
// Here T is a Dart_handle so no need of &
template<typename T>
void read_cmap_dart_node
(const boost::property_tree::ptree::value_type &/*v*/, T /*val*/)
{}
template<typename T>
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &/*v*/, T &/*val*/)
{}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,char &val)
{val=boost::lexical_cast< char >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,unsigned char &val)
{val=boost::lexical_cast< unsigned char >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,short int &val)
{val=boost::lexical_cast< short int >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,unsigned short int &val)
{val=boost::lexical_cast< unsigned short int >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,int &val)
{val=boost::lexical_cast< int >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,unsigned int &val)
{val=boost::lexical_cast< unsigned int >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,long int &val)
{val=boost::lexical_cast< long int >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,unsigned long int &val)
{val=boost::lexical_cast< unsigned long int >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,float &val)
{val=boost::lexical_cast< float >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,double &val)
{val=boost::lexical_cast< double >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,long double &val)
{val=boost::lexical_cast< long double >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,bool &val)
{val=boost::lexical_cast< bool >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,std::string &val)
{val=boost::lexical_cast< std::string >(v.second.data());}
template<> inline
void read_cmap_attribute_node
(const boost::property_tree::ptree::value_type &v,RPoint_3 &val)
{
double x=v.second.get<double>("x");
double y=v.second.get<double>("y");
double z=v.second.get<double>("z");
val = RPoint_3(x,y,z);
}
template<typename CMap, unsigned int i,
bool WithInfo=CGAL::Is_attribute_has_non_void_info
<typename CMap::template Attribute_type<i>::type>::value,
bool WithPoint=CGAL::Is_attribute_has_point
<typename CMap::template Attribute_type<i>::type >::value >
struct My_functor_cmap_load_one_attrib;
// An attrib with point and with info
template<typename CMap, unsigned int i>
struct My_functor_cmap_load_one_attrib<CMap, i, true, true>
{
static void run(const boost::property_tree::ptree& pt, CMap* amap,
const std::vector<typename CMap::Dart_handle>& myDarts)
{
BOOST_FOREACH( const boost::property_tree::ptree::value_type &v0,
pt.get_child("data.attributes") )
{
// <dimension>
if (v0.first == "dimension")
{
int dimension=v0.second.get("<xmlattr>.index", -1);
// if map.dimension == dimension saved in the xml file
if (dimension==i)
{
unsigned int id_dart_cellule=0;
std::string type = v0.second.get<std::string>("type");
std::string type_map=std::string
(typeid(typename CMap::template Attribute_type<i>::type::Info).name());
std::string ptype = v0.second.get<std::string>("type_point");
std::string ptype_map= std::string
(typeid(typename CMap::template Attribute_type<i>::type::Point).name());
// std::cout<<"ptype="<<ptype<<" and type_map="<<type_map<<std::endl;
/* if(type!=type_map && ptype!=ptype_map)
{
// std::cout<<"Not loaded."<<std::endl;
return;
}*/
BOOST_FOREACH(const boost::property_tree::ptree::value_type &v1,
v0.second )
{
if( v1.first == "a" )
{
id_dart_cellule=v1.second.get<unsigned int>("d")-1;
BOOST_FOREACH(const boost::property_tree::ptree::value_type &v2,
v1.second )
{
if( type==type_map && v2.first == "v" )
{
if (myDarts[id_dart_cellule]->
template attribute<i>()==NULL )
amap->template set_attribute<i>
(myDarts[id_dart_cellule],
amap->template create_attribute<i>());
read_cmap_attribute_node
(v2,
myDarts[id_dart_cellule]->
template attribute<i>()->info());
}
if( ptype==ptype_map && v2.first == "p" )
{
if (myDarts[id_dart_cellule]->
template attribute<i>()==NULL )
amap->template set_attribute<i>
(myDarts[id_dart_cellule],
amap->template create_attribute<i>());
read_cmap_attribute_node
(v2,
myDarts[id_dart_cellule]->
template attribute<i>()->point());
}
}
}
}
}
}
}
}
};
// An attribute with point and without info
template<typename CMap, unsigned int i>
struct My_functor_cmap_load_one_attrib<CMap, i, false, true>
{
static void run(const boost::property_tree::ptree& pt, CMap* amap,
const std::vector<typename CMap::Dart_handle>& myDarts)
{
BOOST_FOREACH( const boost::property_tree::ptree::value_type &v0,
pt.get_child("data.attributes") )
{
// <dimension>
if (v0.first == "dimension")
{
int dimension=v0.second.get("<xmlattr>.index", -1);
// if map.dimension == dimension saved in the xml file
if (dimension==i)
{
unsigned int id_dart_cellule=0;
std::string ptype = v0.second.get<std::string>("type_point");
std::string type_map= typeid
(typename CMap::template Attribute_type<i>::type::Point).name();
// std::cout<<"ptype="<<ptype<<" and type_map="<<type_map<<std::endl;
/* if(ptype!=type_map)
{
// std::cout<<"Not loaded."<<std::endl;
return;
}*/
BOOST_FOREACH(const boost::property_tree::ptree::value_type &v1,
v0.second )
{
if( v1.first == "a" )
{
id_dart_cellule=v1.second.get<unsigned int>("d")-1;
BOOST_FOREACH(const boost::property_tree::ptree::value_type &v2,
v1.second )
{
if( v2.first == "p" )
{
if (myDarts[id_dart_cellule]->
template attribute<i>()==NULL )
amap->template set_attribute<i>
(myDarts[id_dart_cellule],
amap->template create_attribute<i>());
read_cmap_attribute_node
(v2,
myDarts[id_dart_cellule]->
template attribute<i>()->point());
}
}
}
}
}
}
}
}
};
// An attribute without point and with info
template<typename CMap, unsigned int i>
struct My_functor_cmap_load_one_attrib<CMap, i, true, false>
{
static void run(const boost::property_tree::ptree& pt, CMap* amap,
const std::vector<typename CMap::Dart_handle>& myDarts)
{
BOOST_FOREACH( const boost::property_tree::ptree::value_type &v0,
pt.get_child("data.attributes") )
{
// <dimension>
if (v0.first == "dimension")
{
int dimension=v0.second.get("<xmlattr>.index", -1);
// if map.dimension == dimension saved in the xml file
if (dimension==i)
{
unsigned int id_dart_cellule=0;
std::string ptype = v0.second.get<std::string>("type");
std::string type_map= typeid
(typename CMap::template Attribute_type<i>::type::Info).name();
// std::cout<<"ptype="<<ptype<<" and type_map="<<type_map<<std::endl;
/* if(ptype!=type_map)
{
// std::cout<<"Not loaded."<<std::endl;
return;
} */
BOOST_FOREACH(const boost::property_tree::ptree::value_type &v1,
v0.second )
{
if( v1.first == "a" )
{
id_dart_cellule=v1.second.get<unsigned int>("d")-1;
BOOST_FOREACH(const boost::property_tree::ptree::value_type &v2,
v1.second )
{
if( v2.first == "v" )
{
if (myDarts[id_dart_cellule]->
template attribute<i>()==NULL )
amap->template set_attribute<i>
(myDarts[id_dart_cellule],
amap->template create_attribute<i>());
read_cmap_attribute_node
(v2,
myDarts[id_dart_cellule]->
template attribute<i>()->info());
}
}
}
}
}
}
}
}
};
// An attribute without point and without info
template<typename CMap, unsigned int i>
struct My_functor_cmap_load_one_attrib<CMap, i, false, false>
{
static void run(const boost::property_tree::ptree& pt, CMap* amap,
const std::vector<typename CMap::Dart_handle>& myDarts)
{
BOOST_FOREACH( const boost::property_tree::ptree::value_type &v0,
pt.get_child("data.attributes") )
{
// <dimension>
if (v0.first == "dimension")
{
int dimension=v0.second.get("<xmlattr>.index", -1);
// if map.dimension == dimension saved in the xml file
if (dimension==i)
{
unsigned int id_dart_cellule=0;
BOOST_FOREACH(const boost::property_tree::ptree::value_type &v1,
v0.second )
{
if( v1.first == "a" )
{
id_dart_cellule=v1.second.get<unsigned int>("d")-1;
if (myDarts[id_dart_cellule]->
template attribute<i>()==NULL )
amap->template set_attribute<i>
(myDarts[id_dart_cellule],
amap->template create_attribute<i>());
}
}
}
}
}
}
};
/** Functor called to load i-attributes.
* @param pt a boost::property_tree::ptree load from an xml file
* @param amap a pointer to the map to load into
* @param myDarts an array of Dart_handle st myDarts[i] is the ith dart.
*/
template<class CMap>
struct My_functor_cmap_load_attrib
{
template <unsigned int i>
static void run(const boost::property_tree::ptree& pt, CMap* amap,
const std::vector<typename CMap::Dart_handle>& myDarts)
{
My_functor_cmap_load_one_attrib<CMap, i>::run(pt, amap, myDarts);
}
};
template < class CMap >
bool cmap_load_darts(boost::property_tree::ptree &pt, CMap& amap,
std::vector<typename CMap::Dart_handle>& myDarts)
{
// use a boost::property_tree
using boost::property_tree::ptree;
// make darts
BOOST_FOREACH( const ptree::value_type &v, pt.get_child("data.darts") )
{
if( v.first == "d" )
myDarts.push_back(amap.create_dart());
}
// update beta links
unsigned int index;
unsigned int currentDartInt = 0;
unsigned int nextDartInt;
BOOST_FOREACH( const ptree::value_type &v, pt.get_child("data.darts") )
{
if( v.first == "d" )
{
BOOST_FOREACH( const ptree::value_type &v2, v.second )
{
if (v2.first == "b")
{
index = v2.second.get("<xmlattr>.i", 0);
nextDartInt = boost::lexical_cast< int >(v2.second.data())-1;
if ( index<=amap.dimension )
{
// A->B
amap.basic_link_beta(myDarts[currentDartInt],
myDarts[nextDartInt],
index);
//B->A
amap.basic_link_beta(myDarts[nextDartInt],
myDarts[currentDartInt],
CGAL_BETAINV(index));
}
}
else if (v2.first=="v")
read_cmap_dart_node(v2,myDarts[currentDartInt]);
}
}
++currentDartInt;
}
return true;
}
template < class CMap >
void cmap_load_attributes(const boost::property_tree::ptree& pt, CMap& amap,
const std::vector<typename CMap::Dart_handle>& myDarts)
{
CMap::Helper::template Foreach_enabled_attributes
<My_functor_cmap_load_attrib<CMap> >::run(pt,&amap,myDarts);
}
template < class CMap >
bool load_combinatorial_map(std::ifstream & input, CMap& amap)
{
using boost::property_tree::ptree;
ptree pt;
read_xml(input, pt);
std::vector<typename CMap::Dart_handle> myDarts;
cmap_load_darts(pt,amap,myDarts);
cmap_load_attributes(pt,amap,myDarts);
return true;
}
template < class CMap >
bool load_combinatorial_map(const char* filename, CMap& amap)
{
std::ifstream input(filename);
if (!input) return false;
return load_combinatorial_map(input, amap);
}
} // namespace CGAL
#endif // CGAL_COMBINATORIAL_MAP_SAVE_LOAD_H //
// EOF //

View File

@ -16,6 +16,7 @@ endif()
## To add expensive tests
# add_definitions("-DCGAL_CHECK_EXPENSIVE")
# add_definitions("-Wall -Wextra")
## For profilling with gprof
# add_definitions("-pg")
@ -72,7 +73,6 @@ target_link_libraries(Linear_cell_complex_3_demo ${CGAL_LIBRARIES}
${CGAL_3RD_PARTY_LIBRARIES})
target_link_libraries(Linear_cell_complex_3_demo ${QT_LIBRARIES}
${QGLVIEWER_LIBRARIES} )
target_link_libraries(Linear_cell_complex_3_demo ${OPENGL_gl_LIBRARY}
${OPENGL_glu_LIBRARY} )
target_link_libraries(Linear_cell_complex_3_demo ${OPENGL_gl_LIBRARY} )
endif()

View File

@ -24,6 +24,8 @@
#include <QSettings>
#include <CGAL/Timer.h>
#include <CGAL/ipower.h>
#include "MainWindow.moc"
#include "import_moka.h"
// Function defined in Linear_cell_complex_3_subivision.cpp
void subdivide_lcc_3 (LCC & m);
@ -58,7 +60,7 @@ MainWindow::MainWindow (QWidget * parent):CGAL::Qt::DemosMainWindow (parent),
labels.append(QString(tr("Hidden")));
volumeList->setHorizontalHeaderLabels(labels);
//volumeList->resizeColumnsToContents();
volumeList->setFixedWidth(200);
volumeList->setFixedWidth(220);
/* volumeList->setColumnWidth(0,85);
volumeList->setColumnWidth(1,35);
volumeList->setColumnWidth(2,35);*/
@ -82,7 +84,7 @@ MainWindow::MainWindow (QWidget * parent):CGAL::Qt::DemosMainWindow (parent),
this->addRecentFiles (this->menuFile, this->actionQuit);
connect (this, SIGNAL (openRecentFile (QString)),
this, SLOT (load_off (QString)));
this, SLOT (load_depend_on_extension(QString)));
statusMessage = new QLabel
("Darts: 0, Vertices: 0 (Points: 0), Edges: 0, Facets: 0,"
@ -223,6 +225,32 @@ void MainWindow::init_all_new_volumes()
{ on_new_volume(it); }
}
void MainWindow::on_actionSave_triggered ()
{
QString fileName = QFileDialog::getSaveFileName (this,
tr ("Save"),
"save.3map",
tr ("3-map files (*.3map)"));
if (!fileName.isEmpty ())
{
save(fileName);
}
}
void MainWindow::on_actionLoad_triggered ()
{
QString fileName = QFileDialog::getOpenFileName (this,
tr ("Load"),
"./3map",
tr ("3-map files (*.3map)"));
if (!fileName.isEmpty ())
{
load(fileName, true);
}
}
void MainWindow::on_actionImportOFF_triggered ()
{
QString fileName = QFileDialog::getOpenFileName (this,
@ -236,6 +264,19 @@ void MainWindow::on_actionImportOFF_triggered ()
}
}
void MainWindow::on_actionImportMoka_triggered()
{
QString fileName = QFileDialog::getOpenFileName (this,
tr ("Import Moka"),
"./moka",
tr ("Moka files (*.moka)"));
if (!fileName.isEmpty ())
{
load_moka(fileName, true);
}
}
void MainWindow::on_actionImport3DTDS_triggered ()
{
QString fileName = QFileDialog::getOpenFileName (this,
@ -264,6 +305,84 @@ void MainWindow::on_actionAddOFF_triggered()
}
}
void MainWindow::load_depend_on_extension(const QString & fileName, bool clear)
{
QString ext = QFileInfo(fileName).suffix();
if ( ext=="3map")
{
load(fileName, clear);
}
else if (ext=="off")
{
load_off(fileName, clear);
}
else if (ext=="moka")
{
load_moka(fileName, clear);
}
else
{
std::cout<<"Extension not considered."<<std::endl;
}
}
void MainWindow::load(const QString & fileName, bool clear)
{
QApplication::setOverrideCursor (Qt::WaitCursor);
if (clear) this->clear_all();
#ifdef CGAL_PROFILE_LCC_DEMO
CGAL::Timer timer;
timer.start();
#endif
bool res = load_combinatorial_map(fileName.toStdString().c_str(), *(scene.lcc));
#ifdef CGAL_PROFILE_LCC_DEMO
timer.stop();
std::cout<<"Time to load 3-map "<<qPrintable(fileName)<<": "
<<timer.time()<<" seconds."<<std::endl;
#endif
recreate_whole_volume_list();
this->addToRecentFiles(fileName);
QApplication::restoreOverrideCursor ();
if (res)
statusBar ()->showMessage (QString ("3-map loaded ") + fileName,
DELAY_STATUSMSG);
else
statusBar ()->showMessage (QString ("Problem: 3-map not loaded ") + fileName,
DELAY_STATUSMSG);
Q_EMIT (sceneChanged ());
}
void MainWindow::save(const QString & fileName)
{
QApplication::setOverrideCursor (Qt::WaitCursor);
#ifdef CGAL_PROFILE_LCC_DEMO
CGAL::Timer timer;
timer.start();
#endif
if ( save_combinatorial_map(*(scene.lcc), fileName.toStdString().c_str()) )
statusBar ()->showMessage (QString ("3-map saved ") + fileName,
DELAY_STATUSMSG);
else
statusBar ()->showMessage (QString ("Problem: 3-map not saved ") + fileName,
DELAY_STATUSMSG);
QApplication::restoreOverrideCursor ();
#ifdef CGAL_PROFILE_LCC_DEMO
timer.stop();
std::cout<<"Time to save 3-map "<<qPrintable(fileName)<<": "
<<timer.time()<<" seconds."<<std::endl;
#endif
}
void MainWindow::load_off (const QString & fileName, bool clear)
{
QApplication::setOverrideCursor (Qt::WaitCursor);
@ -333,6 +452,40 @@ void MainWindow::load_3DTDS (const QString & fileName, bool clear)
Q_EMIT (sceneChanged ());
}
void MainWindow::load_moka(const QString & fileName, bool clear)
{
QApplication::setOverrideCursor (Qt::WaitCursor);
if (clear) this->clear_all();
#ifdef CGAL_PROFILE_LCC_DEMO
CGAL::Timer timer;
timer.start();
#endif
CGAL::import_from_moka < LCC > (*scene.lcc, qPrintable (fileName));
#ifdef CGAL_PROFILE_LCC_DEMO
timer.stop();
std::cout<<"Time to load off "<<qPrintable(fileName)<<": "
<<timer.time()<<" seconds."<<std::endl;
#endif
init_all_new_volumes();
recreate_whole_volume_list();
this->addToRecentFiles (fileName);
QApplication::restoreOverrideCursor ();
if (clear)
statusBar ()->showMessage (QString ("Load off file") + fileName,
DELAY_STATUSMSG);
else
statusBar ()->showMessage (QString ("Add off file") + fileName,
DELAY_STATUSMSG);
Q_EMIT (sceneChanged ());
}
Dart_handle MainWindow::make_iso_cuboid(const Point_3 basepoint, LCC::FT lg)
{
return scene.lcc->make_hexahedron(basepoint,
@ -783,7 +936,7 @@ void MainWindow::on_actionRemove_filled_volumes_triggered()
DELAY_STATUSMSG);
}
void MainWindow::on_actionTriangulate_all_facets_triggered()
void MainWindow::on_actionInsert_center_vertices_triggered()
{
QApplication::setOverrideCursor (Qt::WaitCursor);
@ -805,17 +958,113 @@ void MainWindow::on_actionTriangulate_all_facets_triggered()
#ifdef CGAL_PROFILE_LCC_DEMO
timer.stop();
std::cout<<"Time to triangulate all filled faces: "
std::cout<<"Time to insert center vertices in all filled faces: "
<<timer.time()<<" seconds."<<std::endl;
#endif
QApplication::restoreOverrideCursor ();
Q_EMIT (sceneChanged ());
statusBar()->showMessage
(QString ("Facets of visible and filled volume(s) triangulated"),
(QString ("Vertices are inserted in center of facets of visible and filled volume(s)"),
DELAY_STATUSMSG);
}
double compute_angle3d(const Vector_3& v1, const Vector_3& v2)
{
double a = CGAL::to_double( (v1*v2) /
( sqrt(v1.squared_length()) * sqrt(v2.squared_length()) ) ) ;
if (a < -1.0) return acos(-1.0)/M_PI*180.0;
else if (a > 1.0) return acos(1.0)/M_PI*180.0;
else return acos(a)/M_PI*180.0;
}
void MainWindow::on_actionMerge_coplanar_faces_triggered()
{
QApplication::setOverrideCursor (Qt::WaitCursor);
#ifdef CGAL_PROFILE_LCC_DEMO
CGAL::Timer timer;
timer.start();
#endif
scene.lcc->set_update_attributes(false);
std::vector<Dart_handle> edges;
int treated = scene.lcc->get_new_mark();
int treated2 = scene.lcc->get_new_mark();
for ( LCC::Dart_range::iterator it= scene.lcc->darts().begin(),
itend = scene.lcc->darts().end(); it!=itend; ++it )
{
if (!scene.lcc->is_marked(it, treated) )
{
if ( CGAL::is_removable<LCC, 1>(*scene.lcc, it) )
{
LCC::Vector normal1 = CGAL::compute_normal_of_cell_2(*scene.lcc,it);
LCC::Vector normal2 = CGAL::compute_normal_of_cell_2(*scene.lcc, scene.lcc->beta<2>(it) );
double angle = compute_angle3d(normal1, normal2);
if ( ((angle<5.0 || angle>355.0) || (angle<185.0 && angle>175.0)) )
{
edges.push_back(it);
}
}
CGAL::mark_cell<LCC, 1>(*scene.lcc, it, treated);
}
}
for (std::vector<Dart_handle>::iterator it=edges.begin(),
itend=edges.end(); it!=itend; ++it)
{
CGAL::mark_cell<LCC, 1>(*scene.lcc, *it, treated2);
if ( scene.lcc->beta<0, 2>(*it)==*it || scene.lcc->beta<1, 2>(*it)==*it)
{ // To process dangling edges
Dart_handle actu = *it, prev=NULL;
do
{
if ( scene.lcc->beta<0, 2>(actu)==actu ) prev = scene.lcc->beta<1>(actu);
else prev = scene.lcc->beta<0>(actu);
if (scene.lcc->is_marked(actu, treated2) &&
(scene.lcc->beta<0, 2>(actu)!=actu || scene.lcc->beta<1, 2>(actu)!=actu) )
{
CGAL::remove_cell<LCC, 1>(*scene.lcc, actu);
actu = prev;
}
else
actu = NULL;
}
while (actu!=NULL && (scene.lcc->beta<0, 2>(actu)==actu || scene.lcc->beta<1, 2>(actu)==actu));
}
else if ( !CGAL::belong_to_same_cell<LCC, 2>(*scene.lcc, *it,
scene.lcc->beta<2>(*it)) )
CGAL::remove_cell<LCC, 1>(*scene.lcc, *it);
}
assert(scene.lcc->is_whole_map_marked(treated));
scene.lcc->free_mark(treated);
scene.lcc->free_mark(treated2);
scene.lcc->set_update_attributes(true);
#ifdef CGAL_PROFILE_LCC_DEMO
timer.stop();
std::cout<<"Time to merge all coplanar faces: "
<<timer.time()<<" seconds."<<std::endl;
#endif
recreate_whole_volume_list();
QApplication::restoreOverrideCursor ();
Q_EMIT (sceneChanged ());
statusBar()->showMessage
(QString ("Coplanar face(s) merged"), DELAY_STATUSMSG);
}
void MainWindow::on_actionMerge_all_volumes_triggered()
{
QApplication::setOverrideCursor (Qt::WaitCursor);
@ -861,6 +1110,179 @@ void MainWindow::on_actionMerge_all_volumes_triggered()
(QString ("Visible and filled volume(s) merged"), DELAY_STATUSMSG);
}
bool is_external(CDT::Face_handle fh)
{
return fh->info().is_external;
}
int number_of_existing_edge(CDT::Face_handle fh)
{
unsigned res=0;
for (int i=0; i<3; ++i)
if (fh->info().exist_edge[i]) ++res;
return res;
}
int get_free_edge(CDT::Face_handle fh)
{
CGAL_assertion( number_of_existing_edge(fh)==2 );
for (int i=0; i<3; ++i)
if (!fh->info().exist_edge[i]) return i;
CGAL_assertion(false);
return -1;
}
void constrained_delaunay_triangulation(LCC &lcc, Dart_handle d1)
{
Vector_3 normal = CGAL::compute_normal_of_cell_2(lcc,d1);
P_traits cdt_traits(normal);
CDT cdt(cdt_traits);
//inserting the constraints edge by edge
LCC::Dart_of_orbit_range<1>::iterator
it(lcc.darts_of_orbit<1>(d1).begin());
CDT::Vertex_handle previous=LCC::null_handle, first=LCC::null_handle,
vh=LCC::null_handle;
for (LCC::Dart_of_orbit_range<1>::iterator
itend(lcc.darts_of_orbit<1>(d1).end()); it!=itend; ++it)
{
vh = cdt.insert(lcc.point(it));
vh->info()=it;
if( first==NULL )
{
first=vh;
}
if( previous!=NULL)
{
CGAL_assertion( previous !=vh );
cdt.insert_constraint(previous,vh);
}
previous=vh;
}
cdt.insert_constraint(previous,first);
CGAL_assertion(cdt.is_valid());
// sets mark is_external
for( CDT::All_faces_iterator fit = cdt.all_faces_begin(),
fitend = cdt.all_faces_end(); fit != fitend; ++fit)
{
fit->info().is_external = false;
fit->info().exist_edge[0]=false;
fit->info().exist_edge[1]=false;
fit->info().exist_edge[2]=false;
}
std::queue<CDT::Face_handle> face_queue;
face_queue.push(cdt.infinite_vertex()->face());
while(! face_queue.empty() )
{
CDT::Face_handle fh = face_queue.front();
face_queue.pop();
if(!fh->info().is_external)
{
fh->info().is_external = true;
for(int i = 0; i <3; ++i)
{
if(!cdt.is_constrained(std::make_pair(fh, i)))
{
face_queue.push(fh->neighbor(i));
}
}
}
}
for( CDT::Finite_edges_iterator eit = cdt.finite_edges_begin(),
eitend = cdt.finite_edges_end(); eit != eitend; ++eit)
{
CDT::Face_handle fh = eit->first;
int index = eit->second;
CDT::Face_handle opposite_fh = fh->neighbor(index);
if(cdt.is_constrained(std::make_pair(fh, index)))
{
fh->info().exist_edge[index]=true;
opposite_fh->info().exist_edge[cdt.mirror_index(fh,index)]=true;
if ( !fh->info().is_external && number_of_existing_edge(fh)==2 )
face_queue.push(fh);
if ( !opposite_fh->info().is_external &&
number_of_existing_edge(opposite_fh)==2 )
face_queue.push(opposite_fh);
}
}
while( !face_queue.empty() )
{
CDT::Face_handle fh = face_queue.front();
face_queue.pop();
CGAL_assertion( number_of_existing_edge(fh)>=2 ); // i.e. ==2 or ==3
CGAL_assertion( !fh->info().is_external );
if (number_of_existing_edge(fh)==2)
{
int index = get_free_edge(fh);
CDT::Face_handle opposite_fh = fh->neighbor(index);
CGAL_assertion( !fh->info().exist_edge[index] );
CGAL_assertion( !opposite_fh->info().
exist_edge[cdt.mirror_index(fh,index)] );
const CDT::Vertex_handle va = fh->vertex(cdt. cw(index));
const CDT::Vertex_handle vb = fh->vertex(cdt.ccw(index));
Dart_handle ndart=
CGAL::insert_cell_1_in_cell_2(lcc,va->info(),vb->info());
va->info()=lcc.beta<2>(ndart);
fh->info().exist_edge[index]=true;
opposite_fh->info().exist_edge[cdt.mirror_index(fh,index)]=true;
if ( !opposite_fh->info().is_external &&
number_of_existing_edge(opposite_fh)==2 )
face_queue.push(opposite_fh);
}
}
}
void MainWindow::on_actionTriangulate_all_facets_triggered()
{
QApplication::setOverrideCursor (Qt::WaitCursor);
#ifdef CGAL_PROFILE_LCC_DEMO
CGAL::Timer timer;
timer.start();
#endif
std::vector<LCC::Dart_handle> v;
for (LCC::One_dart_per_cell_range<2>::iterator
it(scene.lcc->one_dart_per_cell<2>().begin()); it.cont(); ++it)
{
if ( scene.lcc->info<3>(it).is_filled_and_visible() ||
(!scene.lcc->is_free<3>(it) &&
scene.lcc->info<3>(scene.lcc->beta<3>(it)).is_filled_and_visible()) )
v.push_back(it);
}
for (std::vector<LCC::Dart_handle>::iterator itv(v.begin());
itv!=v.end(); ++itv)
constrained_delaunay_triangulation(*scene.lcc, *itv);
#ifdef CGAL_PROFILE_LCC_DEMO
timer.stop();
std::cout<<"Time to triangulate all filled faces: "
<<timer.time()<<" seconds."<<std::endl;
#endif
recreate_whole_volume_list();
QApplication::restoreOverrideCursor ();
Q_EMIT (sceneChanged ());
statusBar()->showMessage
(QString ("All visible and filled faces were triangulated"), DELAY_STATUSMSG);
}
bool MainWindow::is_volume_in_list(LCC::Attribute_handle<3>::type ah)
{
for(int row=0; row < volumeList->rowCount(); ++row)
@ -975,6 +1397,8 @@ void MainWindow::recreate_whole_volume_list()
void MainWindow::onCellChanged(int row, int col)
{
volumeList->disconnect(this);
LCC::Attribute_type<3>::type* ptr=
reinterpret_cast<LCC::Attribute_type<3>::type*>
( volumeList->item(row,3)->data(Qt::UserRole).value<quintptr>() );
@ -994,6 +1418,7 @@ void MainWindow::onCellChanged(int row, int col)
(volumeList->item(row,1)->flags()|Qt::ItemIsEnabled);
}
connectVolumeListHandlers();
Q_EMIT( sceneChanged());
}
@ -1875,64 +2300,6 @@ void MainWindow::onSierpinskiCarpetUpdateAttributes(bool newValue)
sierpinskiCarpetUpdateAttributes = newValue;
}
/*void MainWindow::onSierpinskiCarpetNeverUpdateAttributes(bool newValue)
{
if (afterConstructionUpdateAttributes)
{
dialogsierpinskicarpet.groupBox2->setEnabled(false);
}
neverUpdateAttributes = true;
duringConstructionUpdateAttributes = false;
afterConstructionUpdateAttributes = false;
}
void MainWindow::onSierpinskiCarpetDuringConstructionUpdateAttributes(bool newValue)
{
if (afterConstructionUpdateAttributes)
{
dialogsierpinskicarpet.groupBox2->setEnabled(false);
}
neverUpdateAttributes = false;
duringConstructionUpdateAttributes = true;
afterConstructionUpdateAttributes = false;
}
void MainWindow::onSierpinskiCarpetAfterConstructionUpdateAttributes(bool newValue)
{
if (!afterConstructionUpdateAttributes)
{
dialogsierpinskicarpet.groupBox2->setEnabled(true);
}
neverUpdateAttributes = false;
duringConstructionUpdateAttributes = false;
afterConstructionUpdateAttributes = true;
}
void MainWindow::onSierpinskiCarpetUpdateAttributesMethodStdMap(bool newValue)
{
updateAttributesMethodStdMap = true;
updateAttributesMethodTraversal = false;
}
void MainWindow::onSierpinskiCarpetUpdateAttributesMethodTraversal(bool newValue)
{
updateAttributesMethodStdMap = false;
updateAttributesMethodTraversal = true;
}
void MainWindow::onSierpinskiCarpetComputeGeometry(bool newValue)
{
sierpinski_carpet_compute_geometry();
computeGeometry = false;
dialogsierpinskicarpet.computeGeometry->setEnabled(false);
Q_EMIT( sceneChanged());
}*/
void MainWindow::onSierpinskiCarpetInc()
{
QApplication::setOverrideCursor (Qt::WaitCursor);

View File

@ -110,9 +110,12 @@ public:
public Q_SLOTS:
// File menu
void on_actionSave_triggered();
void on_actionLoad_triggered();
void on_actionImportOFF_triggered();
void on_actionAddOFF_triggered();
void on_actionImport3DTDS_triggered();
void on_actionImportMoka_triggered();
void on_actionCompute_Voronoi_3D_triggered();
void on_actionClear_triggered();
@ -130,19 +133,25 @@ public Q_SLOTS:
void on_actionSubdivide_pqq_triggered();
void on_actionDual_3_triggered();
void on_actionClose_volume_triggered();
void on_actionTriangulate_all_facets_triggered();
void on_actionSew3_same_facets_triggered();
void on_actionUnsew3_all_triggered();
void on_actionMerge_coplanar_faces_triggered();
void on_actionMerge_all_volumes_triggered();
void on_actionRemove_filled_volumes_triggered();
void on_actionInsert_center_vertices_triggered();
void on_actionTriangulate_all_facets_triggered();
// View menu
void on_actionExtend_filled_volumes_triggered();
void on_actionExtend_hidden_volumes_triggered();
// Other slots
void load_depend_on_extension(const QString& fileName, bool clear=true);
void load(const QString& fileName, bool clear=true);
void save(const QString& fileName);
void load_off(const QString& fileName, bool clear=true);
void load_3DTDS(const QString& fileName, bool clear=true);
void load_moka(const QString& fileName, bool clear=true);
void onSceneChanged();

View File

@ -33,15 +33,19 @@
<x>0</x>
<y>0</y>
<width>635</width>
<height>22</height>
<height>25</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="actionLoad"/>
<addaction name="actionSave"/>
<addaction name="separator"/>
<addaction name="actionImportOFF"/>
<addaction name="actionAddOFF"/>
<addaction name="actionImportMoka"/>
<addaction name="separator"/>
<addaction name="actionImport3DTDS"/>
<addaction name="actionCompute_Voronoi_3D"/>
@ -54,12 +58,15 @@
<property name="title">
<string>&amp;Operations</string>
</property>
<addaction name="actionInsert_center_vertices"/>
<addaction name="actionTriangulate_all_facets"/>
<addaction name="actionSew3_same_facets"/>
<addaction name="actionUnsew3_all"/>
<addaction name="actionMerge_coplanar_faces"/>
<addaction name="actionMerge_all_volumes"/>
<addaction name="actionRemove_filled_volumes"/>
<addaction name="separator"/>
<addaction name="actionSew3_same_facets"/>
<addaction name="actionUnsew3_all"/>
<addaction name="separator"/>
<addaction name="actionSubdivide"/>
<addaction name="actionSubdivide_pqq"/>
<addaction name="actionClose_volume"/>
@ -221,6 +228,31 @@
<string>Create Sierpinski Triangle</string>
</property>
</action>
<action name="actionLoad">
<property name="text">
<string>&amp;Load</string>
</property>
</action>
<action name="actionSave">
<property name="text">
<string>&amp;Save</string>
</property>
</action>
<action name="actionImportMoka">
<property name="text">
<string>Import Moka</string>
</property>
</action>
<action name="actionMerge_coplanar_faces">
<property name="text">
<string>Merge coplanar faces</string>
</property>
</action>
<action name="actionInsert_center_vertices">
<property name="text">
<string>Insert center vertices in faces</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

File diff suppressed because it is too large Load Diff

View File

@ -22,57 +22,29 @@
#define VIEWER_H
#include "typedefs.h"
#include <vector>
#include <QGLViewer/qglviewer.h>
#include <QKeyEvent>
#include <QOpenGLFunctions_2_1>
#include <QOpenGLVertexArrayObject>
#include <QGLBuffer>
#include <QOpenGLShaderProgram>
class Viewer : public QGLViewer, QOpenGLFunctions_2_1
class Viewer : public QGLViewer, public QOpenGLFunctions_2_1
{
Q_OBJECT
CGAL::Timer timer;
Scene* scene;
bool wireframe;
bool flatShading;
bool edges;
bool vertices;
CGAL::Bbox_3 bb;
GLuint m_dlFaces;
GLuint m_dlFacesFlat;
GLuint m_dlEdges;
GLuint m_dlVertices;
bool m_displayListCreated;
typedef LCC::Dart_handle Dart_handle;
typedef LCC::Dart_const_handle Dart_const_handle;
public:
Viewer(QWidget* parent);
~Viewer()
{
buffers[0].destroy();
buffers[1].destroy();
buffers[2].destroy();
buffers[3].destroy();
buffers[4].destroy();
buffers[5].destroy();
buffers[6].destroy();
buffers[7].destroy();
vao[0].destroy();
vao[1].destroy();
vao[2].destroy();
vao[3].destroy();
}
~Viewer();
void setScene(Scene* scene_)
{
scene = scene_;
}
{ scene = scene_; }
public:
void draw();
@ -87,12 +59,27 @@ public Q_SLOTS:
void sceneChanged();
private:
void initialize_buffers();
void attrib_buffers(QGLViewer*);
void compile_shaders();
void compute_elements();
void compute_faces(Dart_handle dh);
void compute_edges(Dart_handle dh);
void compute_vertices(Dart_handle dh, bool empty);
private:
Scene* scene;
bool wireframe;
bool flatShading;
bool edges;
bool vertices;
CGAL::Bbox_3 bb;
bool m_previous_scene_empty;
bool are_buffers_initialized;
//Shaders elements
//Shaders elements
int vertexLocation[3];
int normalsLocation;
int mvpLocation[2];
@ -101,24 +88,17 @@ private:
int colorsLocation;
int lightLocation[5];
std::vector<float> pos_points;
std::vector<float> pos_lines;
std::vector<float> pos_facets;
std::vector<float> smooth_normals;
std::vector<float> flat_normals;
std::vector <float> colors;
std::vector<float> colors;
QGLBuffer buffers[10];
QOpenGLVertexArrayObject vao[10];
QOpenGLShaderProgram rendering_program;
QOpenGLShaderProgram rendering_program_p_l;
void initialize_buffers();
void compute_elements();
void attrib_buffers(QGLViewer*);
void compile_shaders();
void triangulate_facet();
bool is_Triangulated();
};
#endif

View File

@ -0,0 +1,192 @@
// Copyright (c) 2011 CNRS and LIRIS' Establishments (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 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$
//
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
//
#ifndef IMPORT_MOKA_H
#define IMPORT_MOKA_H
namespace CGAL
{
struct GDart
{
unsigned int alpha[4];
Dart_handle dh;
LCC::Vertex_attribute_handle vh;
GDart() : dh(NULL), vh(NULL)
{}
GDart(const GDart& adart) : dh(adart.dh),
vh(adart.vh)
{
for (unsigned int i=0; i<4; ++i)
alpha[i]=adart.alpha[i];
}
};
template<typename LCC>
bool import_from_moka(LCC& lcc, const char* filename)
{
typedef typename LCC::Point Point;
std::ifstream ifile(filename);
if (!ifile)
{
std::cout<<"Error opening file "<<filename<<"."<<std::endl;
return false;
}
std::string line;
std::getline(ifile, line);
if ( line == "Moka file [binary]" )
{
std::cout<<"Binary file not (yet) considered.\n";
return false;
}
else if ( line != "Moka file [ascii]" )
{
std::cout<<"File "<<filename<<" is not a moka file.\n";
std::cout<< line;
return false;
}
// To skip the masks mark (TODO read the marks ?)
std::getline(ifile, line);
std::vector<GDart> gdarts;
unsigned int nbLoaded = 0;
unsigned int number;
double x,y,z;
// First load all the gdarts, and create vertex attributes
while(ifile)
{
GDart agdart;
ifile>>agdart.alpha[0]>>agdart.alpha[1]
>>agdart.alpha[2]>>agdart.alpha[3]; // the 4 alpha
ifile>>number>>number>>number>>number; // to skip the 4*8 marks
if ( agdart.alpha[0]==nbLoaded )
{
std::cout<<"Impossible to load a moka file with 0-free darts.\n";
return false;
}
if ( ifile )
{
ifile>>number; // bool to know if dart has a vertex of not.
if (number)
{
ifile>>x>>y>>z;
agdart.vh = lcc.create_vertex_attribute(Point(x, y, z));
}
gdarts.push_back(agdart);
++nbLoaded;
}
}
ifile.close();
// Second orient the gmap, and create oriented darts.
std::stack<unsigned int> totreat;
for (unsigned int startingdart = 0; startingdart<nbLoaded; ++startingdart)
{
bool orient=(gdarts[startingdart].dh==NULL);
for (unsigned int dim=0; orient && dim<4; ++dim)
if (gdarts[gdarts[startingdart].alpha[dim]].dh!=NULL) orient=false;
if ( orient )
{
totreat.push(startingdart);
gdarts[startingdart].dh=lcc.create_dart();
while ( !totreat.empty() )
{
unsigned int i=totreat.top();
totreat.pop();
assert(gdarts[i].dh!=NULL);
for (unsigned int dim=1; dim<4; ++dim)
{
if (gdarts[i].alpha[dim]!=i &&
gdarts[gdarts[i].alpha[dim]].vh!=NULL)
{
gdarts[i].vh = gdarts[gdarts[i].alpha[dim]].vh;
gdarts[gdarts[i].alpha[dim]].vh = NULL;
}
unsigned int alpha0 = gdarts[i].alpha[0];
assert( alpha0!=i );
if (gdarts[alpha0].alpha[dim]!=alpha0)
{
if ( gdarts[gdarts[alpha0].alpha[dim]].dh==NULL )
{
totreat.push(gdarts[alpha0].alpha[dim]);
gdarts[gdarts[alpha0].alpha[dim]].dh = lcc.create_dart();
lcc.basic_link_beta(gdarts[i].dh,
gdarts[gdarts[alpha0].alpha[dim]].dh,
dim);
}
else if (lcc.is_free(gdarts[i].dh, dim))
{
lcc.basic_link_beta(gdarts[i].dh,
gdarts[gdarts[alpha0].alpha[dim]].dh,
dim);
}
}
}
}
}
}
// Test that the gmap was orientable.
bool orientable = true;
for (unsigned int i = 0; i<nbLoaded; ++i)
{
if (gdarts[i].dh!=NULL)
{
for (unsigned int dim=0; dim<4; ++dim)
{
if (orientable &&
gdarts[i].alpha[dim]!=i &&
gdarts[gdarts[i].alpha[dim]].dh!=NULL)
{
std::cout<<"Pb, the gmap is NOT orientable."<<std::endl;
orientable=false;
// lcc.clear();
}
}
if ( gdarts[i].dh->attribute<3>() == NULL )
{
lcc.template set_attribute<3>(gdarts[i].dh, lcc.template create_attribute<3>());
}
}
if (gdarts[i].vh!=NULL)
{
lcc.set_vertex_attribute(gdarts[i].dh, gdarts[i].vh);
}
}
return true;
}
}
#endif

View File

@ -24,6 +24,13 @@
#include <CGAL/Linear_cell_complex_constructors.h>
#include <CGAL/Linear_cell_complex_operations.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Combinatorial_map_save_load.h>
#include <CGAL/Triangulation_2_filtered_projection_traits_3.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Triangulation_face_base_with_info_2.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Constrained_triangulation_plus_2.h>
#include <CGAL/IO/Color.h>
#include <CGAL/Timer.h>
@ -45,6 +52,11 @@ extern CGAL::Random myrandom;
class Volume_info
{
friend void CGAL::read_cmap_attribute_node<Volume_info>
(const boost::property_tree::ptree::value_type &v,Volume_info &val);
friend void CGAL::write_cmap_attribute_node<Volume_info>(boost::property_tree::ptree & node,
const Volume_info& arg);
public:
Volume_info() : m_color(CGAL::Color(myrandom.get_int(0,256),
myrandom.get_int(0,256),
@ -91,22 +103,61 @@ public:
void negate_filled()
{ set_filled(!is_filled()); }
private:
private:
CGAL::Color m_color;
char m_status;
};
namespace CGAL
{
template<>
inline void read_cmap_attribute_node<Volume_info>
(const boost::property_tree::ptree::value_type &v,Volume_info &val)
{
try
{
val.m_status = v.second.get<int>("status");
}
catch(const std::exception & )
{}
try
{
char r = v.second.get<int>("color-r");
char g = v.second.get<int>("color-g");
char b = v.second.get<int>("color-b");
val.m_color = CGAL::Color(r,g,b);
}
catch(const std::exception & )
{}
}
// Definition of function allowing to save custon information.
template<>
inline void write_cmap_attribute_node<Volume_info>(boost::property_tree::ptree & node,
const Volume_info& arg)
{
boost::property_tree::ptree & nValue = node.add("v","");
nValue.add("status",(int)arg.m_status);
nValue.add("color-r",(int)arg.m_color.r());
nValue.add("color-g",(int)arg.m_color.g());
nValue.add("color-b",(int)arg.m_color.b());
}
}
class Myitems
{
public:
template < class Refs >
struct Dart_wrapper
struct Dart_wrapper
{
typedef CGAL::Dart<3, Refs > Dart;
typedef CGAL::Cell_attribute_with_point< Refs > Vertex_attrib;
typedef CGAL::Cell_attribute< Refs, Volume_info> Volume_attrib;
typedef CGAL::cpp11::tuple<Vertex_attrib,void,void,
Volume_attrib> Attributes;
};
@ -124,6 +175,22 @@ typedef LCC::Vector Vector_3;
typedef CGAL::Timer Timer;
typedef CGAL::Triangulation_2_filtered_projection_traits_3<Mytraits> P_traits;
typedef CGAL::Triangulation_vertex_base_with_info_2<Dart_handle,P_traits> Vb;
struct Face_info {
bool exist_edge[3];
bool is_external;
};
typedef CGAL::Triangulation_face_base_with_info_2<Face_info,P_traits> Fb1;
typedef CGAL::Constrained_triangulation_face_base_2<P_traits, Fb1> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
typedef CGAL::No_intersection_tag Itag;
typedef CGAL::Constrained_Delaunay_triangulation_2<P_traits, TDS,
Itag> CDT;
struct Scene {
LCC* lcc;
};