mirror of https://github.com/CGAL/cgal
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:
commit
69706c7de9
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 //
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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>&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>&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>&Load</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave">
|
||||
<property name="text">
|
||||
<string>&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>
|
||||
|
|
|
|||
|
|
@ -16,208 +16,50 @@
|
|||
// $Id$
|
||||
//
|
||||
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
|
||||
// Kumar Snehasish <kumar.snehasish@gmail.com>
|
||||
// Contributor(s): Kumar Snehasish <kumar.snehasish@gmail.com>
|
||||
//
|
||||
#include "Viewer.h"
|
||||
#include <vector>
|
||||
#include <CGAL/bounding_box.h>
|
||||
#include <QGLViewer/vec.h>
|
||||
#include <CGAL/Linear_cell_complex_operations.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/Triangulation_2_filtered_projection_traits_3.h>
|
||||
#include <CGAL/Linear_cell_complex_operations.h>
|
||||
#include <CGAL/bounding_box.h>
|
||||
#include <CGAL/Qt/CreateOpenGLContext.h>
|
||||
|
||||
#include <QGLViewer/vec.h>
|
||||
#include <QDebug>
|
||||
|
||||
typedef LCC::Traits Traits;
|
||||
typedef CGAL::Triangulation_2_filtered_projection_traits_3<Traits> P_traits;
|
||||
struct Face_info {
|
||||
LCC::Dart_handle e[3];
|
||||
bool is_external;
|
||||
};
|
||||
typedef CGAL::Triangulation_vertex_base_with_info_2<Dart_handle,
|
||||
P_traits> Vb;
|
||||
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> CDTbase;
|
||||
typedef CGAL::Constrained_triangulation_plus_2<CDTbase> CDT;
|
||||
|
||||
Viewer::Viewer(QWidget* parent)
|
||||
: QGLViewer(CGAL::Qt::createOpenGLContext(),parent), wireframe(false), flatShading(true),
|
||||
edges(true), vertices(true), m_displayListCreated(false)
|
||||
: QGLViewer(CGAL::Qt::createOpenGLContext(),parent), wireframe(false),
|
||||
flatShading(true), edges(true), vertices(true),
|
||||
m_previous_scene_empty(true), are_buffers_initialized(false)
|
||||
|
||||
{
|
||||
QGLFormat newFormat = this->format();
|
||||
newFormat.setSampleBuffers(true);
|
||||
newFormat.setSamples(16);
|
||||
this->setFormat(newFormat);
|
||||
are_buffers_initialized = false;
|
||||
}
|
||||
//Make sure all the facets are triangles
|
||||
bool
|
||||
Viewer::is_Triangulated()
|
||||
{
|
||||
|
||||
LCC &lcc = *scene->lcc;
|
||||
for (LCC::Attribute_range<3>::type::iterator
|
||||
it=lcc.attributes<3>().begin(),
|
||||
itend=lcc.attributes<3>().end(); it!=itend; ++it )
|
||||
{
|
||||
|
||||
for(LCC::One_dart_per_incident_cell_range<2,3>::iterator
|
||||
dartIter=lcc.one_dart_per_incident_cell<2,3>
|
||||
(lcc.dart_of_attribute<3>(it)).begin(); dartIter.cont(); ++dartIter)
|
||||
{
|
||||
int nb_points_per_facet =0;
|
||||
for (LCC::Dart_of_orbit_range<1>::const_iterator
|
||||
orbitIter = lcc.darts_of_orbit<1>(dartIter).begin();
|
||||
orbitIter.cont(); ++orbitIter)
|
||||
{
|
||||
nb_points_per_facet++;
|
||||
}
|
||||
if(nb_points_per_facet != 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Viewer::triangulate_facet()
|
||||
Viewer::~Viewer()
|
||||
{
|
||||
|
||||
|
||||
pos_facets.resize(0);
|
||||
flat_normals.resize(0);
|
||||
smooth_normals.resize(0);
|
||||
colors.resize(0);
|
||||
|
||||
LCC &lcc = *scene->lcc;
|
||||
|
||||
for (LCC::Attribute_range<3>::type::iterator
|
||||
it=lcc.attributes<3>().begin(),
|
||||
itend=lcc.attributes<3>().end(); it!=itend; ++it )
|
||||
{
|
||||
if ( it->info().is_visible() )
|
||||
{
|
||||
for(LCC::One_dart_per_incident_cell_range<2,3>::iterator
|
||||
dartIter=lcc.one_dart_per_incident_cell<2,3>
|
||||
(lcc.dart_of_attribute<3>(it)).begin(); dartIter.cont(); ++dartIter)
|
||||
{
|
||||
|
||||
//Computes the normal of the facet
|
||||
Traits::Vector_3 normal = CGAL::compute_normal_of_cell_2(lcc,dartIter);
|
||||
normal = normal/(CGAL::sqrt(normal*normal));
|
||||
|
||||
P_traits cdt_traits(normal);
|
||||
CDT cdt(cdt_traits);
|
||||
|
||||
LCC::Dart_of_orbit_range<1>::const_iterator
|
||||
he_circ = lcc.darts_of_orbit<1>(dartIter).begin(),
|
||||
he_circ_end = lcc.darts_of_orbit<1>(dartIter).end();
|
||||
|
||||
// Iterates on the vector of facet handles
|
||||
CDT::Vertex_handle previous, first;
|
||||
do {
|
||||
CDT::Vertex_handle vh = cdt.insert(lcc.point(he_circ));
|
||||
if(first == 0) {
|
||||
first = vh;
|
||||
}
|
||||
//vh->info() = he_circ;
|
||||
if(previous != 0 && previous != vh) {
|
||||
cdt.insert_constraint(previous, vh);
|
||||
}
|
||||
previous = vh;
|
||||
} while( ++he_circ != he_circ_end );
|
||||
cdt.insert_constraint(previous, first);
|
||||
|
||||
// sets mark is_external
|
||||
for(CDT::All_faces_iterator
|
||||
fit = cdt.all_faces_begin(),
|
||||
end = cdt.all_faces_end();
|
||||
fit != end; ++fit)
|
||||
{
|
||||
fit->info().is_external = false;
|
||||
}
|
||||
//check if the facet is external or internal
|
||||
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) continue;
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//iterates on the internal faces to add the vertices to the positions
|
||||
//and the normals to the appropriate vectors
|
||||
for(CDT::Finite_faces_iterator
|
||||
ffit = cdt.finite_faces_begin(),
|
||||
end = cdt.finite_faces_end();
|
||||
ffit != end; ++ffit)
|
||||
{
|
||||
if(ffit->info().is_external)
|
||||
continue;
|
||||
|
||||
//compute normals (no smooth for non-triangle facets objects
|
||||
LCC::Vector normal = CGAL::compute_normal_of_cell_2(lcc,dartIter);
|
||||
normal = normal/(CGAL::sqrt(normal*normal));
|
||||
|
||||
smooth_normals.push_back(normal.x());smooth_normals.push_back(normal.y());smooth_normals.push_back(normal.z());
|
||||
smooth_normals.push_back(normal.x());smooth_normals.push_back(normal.y());smooth_normals.push_back(normal.z());
|
||||
smooth_normals.push_back(normal.x());smooth_normals.push_back(normal.y());smooth_normals.push_back(normal.z());
|
||||
|
||||
flat_normals.push_back(normal.x());flat_normals.push_back(normal.y());flat_normals.push_back(normal.z());
|
||||
flat_normals.push_back(normal.x());flat_normals.push_back(normal.y());flat_normals.push_back(normal.z());
|
||||
flat_normals.push_back(normal.x());flat_normals.push_back(normal.y());flat_normals.push_back(normal.z());
|
||||
|
||||
|
||||
|
||||
pos_facets.push_back(ffit->vertex(0)->point().x()); pos_facets.push_back(ffit->vertex(0)->point().y()); pos_facets.push_back(ffit->vertex(0)->point().z());
|
||||
pos_facets.push_back(ffit->vertex(1)->point().x()); pos_facets.push_back(ffit->vertex(1)->point().y()); pos_facets.push_back(ffit->vertex(1)->point().z());
|
||||
pos_facets.push_back(ffit->vertex(2)->point().x()); pos_facets.push_back(ffit->vertex(2)->point().y()); pos_facets.push_back(ffit->vertex(2)->point().z());
|
||||
|
||||
double r = (double)lcc.info<3>(dartIter).color().r()/255.0;
|
||||
double g = (double)lcc.info<3>(dartIter).color().g()/255.0;
|
||||
double b = (double)lcc.info<3>(dartIter).color().b()/255.0;
|
||||
if ( !lcc.is_free(dartIter, 3) )
|
||||
{
|
||||
r += (double)lcc.info<3>(lcc.beta(dartIter,3)).color().r()/255.0;
|
||||
g += (double)lcc.info<3>(lcc.beta(dartIter,3)).color().g()/255.0;
|
||||
b += (double)lcc.info<3>(lcc.beta(dartIter,3)).color().b()/255.0;
|
||||
r /= 2; g /= 2; b /= 2;
|
||||
}
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
void Viewer::compile_shaders()
|
||||
{
|
||||
if(! buffers[0].create() || !buffers[1].create() || !buffers[2].create() || !buffers[3].create()
|
||||
|| !buffers[4].create() || !buffers[5].create() || !buffers[6].create()
|
||||
|| !buffers[7].create())
|
||||
if(!buffers[0].create() || !buffers[1].create() || !buffers[2].create() ||
|
||||
!buffers[3].create() || !buffers[4].create() || !buffers[5].create() ||
|
||||
!buffers[6].create() || !buffers[7].create())
|
||||
{
|
||||
std::cerr<<"VBO Creation FAILED"<<std::endl;
|
||||
}
|
||||
|
|
@ -281,6 +123,7 @@ void Viewer::compile_shaders()
|
|||
"} \n"
|
||||
"\n"
|
||||
};
|
||||
|
||||
QOpenGLShader *vertex_shader = new QOpenGLShader(QOpenGLShader::Vertex);
|
||||
if(!vertex_shader->compileSourceCode(vertex_source))
|
||||
{
|
||||
|
|
@ -328,6 +171,7 @@ void Viewer::compile_shaders()
|
|||
"} \n"
|
||||
"\n"
|
||||
};
|
||||
|
||||
vertex_shader = new QOpenGLShader(QOpenGLShader::Vertex);
|
||||
if(!vertex_shader->compileSourceCode(vertex_source_p_l))
|
||||
{
|
||||
|
|
@ -353,42 +197,46 @@ void Viewer::compile_shaders()
|
|||
std::cerr<<"linking Program FAILED"<<std::endl;
|
||||
}
|
||||
rendering_program_p_l.bind();
|
||||
|
||||
}
|
||||
|
||||
void Viewer::initialize_buffers()
|
||||
{
|
||||
//The facets
|
||||
vao[0].bind();
|
||||
//points of the facets
|
||||
vao[0].bind();
|
||||
buffers[0].bind();
|
||||
buffers[0].allocate(pos_facets.data(), static_cast<int>(pos_facets.size()*sizeof(float)));
|
||||
buffers[0].allocate(pos_facets.data(),
|
||||
static_cast<int>(pos_facets.size()*sizeof(float)));
|
||||
vertexLocation[0] = rendering_program.attributeLocation("vertex");
|
||||
rendering_program.bind();
|
||||
rendering_program.enableAttributeArray(vertexLocation[0]);
|
||||
rendering_program.setAttributeBuffer(vertexLocation[0],GL_FLOAT,0,3);
|
||||
rendering_program.release();
|
||||
buffers[0].release();
|
||||
|
||||
//normals of the facets
|
||||
buffers[1].bind();
|
||||
buffers[1].allocate(flat_normals.data(), static_cast<int>(flat_normals.size()*sizeof(float)));
|
||||
buffers[1].allocate(flat_normals.data(),
|
||||
static_cast<int>(flat_normals.size()*sizeof(float)));
|
||||
normalsLocation = rendering_program.attributeLocation("normal");
|
||||
rendering_program.bind();
|
||||
rendering_program.enableAttributeArray(normalsLocation);
|
||||
rendering_program.setAttributeBuffer(normalsLocation,GL_FLOAT,0,3);
|
||||
buffers[1].release();
|
||||
|
||||
//colors of the facets
|
||||
buffers[2].bind();
|
||||
buffers[2].allocate(colors.data(), static_cast<int>(colors.size()*sizeof(float)));
|
||||
buffers[2].allocate(colors.data(),
|
||||
static_cast<int>(colors.size()*sizeof(float)));
|
||||
colorsLocation = rendering_program.attributeLocation("color");
|
||||
rendering_program.bind();
|
||||
rendering_program.enableAttributeArray(colorsLocation);
|
||||
rendering_program.setAttributeBuffer(colorsLocation,GL_FLOAT,0,3);
|
||||
buffers[2].release();
|
||||
rendering_program.release();
|
||||
vao[0].release();
|
||||
|
||||
vao[0].release();
|
||||
vao[1].bind();
|
||||
|
||||
//points of the facets
|
||||
buffers[3].bind();
|
||||
buffers[3].allocate(pos_facets.data(), static_cast<int>(pos_facets.size()*sizeof(float)));
|
||||
|
|
@ -398,14 +246,17 @@ void Viewer::initialize_buffers()
|
|||
rendering_program.setAttributeBuffer(vertexLocation[0],GL_FLOAT,0,3);
|
||||
rendering_program.release();
|
||||
buffers[3].release();
|
||||
|
||||
//normals of the facets
|
||||
buffers[4].bind();
|
||||
buffers[4].allocate(smooth_normals.data(), static_cast<int>(smooth_normals.size()*sizeof(float)));
|
||||
buffers[4].allocate(smooth_normals.data(),
|
||||
static_cast<int>(smooth_normals.size()*sizeof(float)));
|
||||
normalsLocation = rendering_program.attributeLocation("normal");
|
||||
rendering_program.bind();
|
||||
rendering_program.enableAttributeArray(normalsLocation);
|
||||
rendering_program.setAttributeBuffer(normalsLocation,GL_FLOAT,0,3);
|
||||
buffers[4].release();
|
||||
|
||||
//colors of the facets
|
||||
buffers[5].bind();
|
||||
buffers[5].allocate(colors.data(), static_cast<int>(colors.size()*sizeof(float)));
|
||||
|
|
@ -415,6 +266,7 @@ void Viewer::initialize_buffers()
|
|||
rendering_program.setAttributeBuffer(colorsLocation,GL_FLOAT,0,3);
|
||||
buffers[5].release();
|
||||
rendering_program.release();
|
||||
|
||||
vao[1].release();
|
||||
|
||||
//The lines
|
||||
|
|
@ -442,57 +294,144 @@ void Viewer::initialize_buffers()
|
|||
vao[3].release();
|
||||
|
||||
are_buffers_initialized = true;
|
||||
|
||||
}
|
||||
|
||||
void Viewer::compute_elements()
|
||||
void Viewer::compute_faces(Dart_handle dh)
|
||||
{
|
||||
|
||||
//Facets
|
||||
if(is_Triangulated())
|
||||
{
|
||||
pos_facets.resize(0);
|
||||
flat_normals.resize(0);
|
||||
smooth_normals.resize(0);
|
||||
colors.resize(0);
|
||||
LCC &lcc = *scene->lcc;
|
||||
|
||||
for (LCC::Attribute_range<3>::type::iterator
|
||||
it=lcc.attributes<3>().begin(),
|
||||
itend=lcc.attributes<3>().end(); it!=itend; ++it )
|
||||
{
|
||||
if ( it->info().is_visible() )
|
||||
{
|
||||
for(LCC::One_dart_per_incident_cell_range<2,3>::iterator
|
||||
dartIter=lcc.one_dart_per_incident_cell<2,3>
|
||||
(lcc.dart_of_attribute<3>(it)).begin(); dartIter.cont(); ++dartIter)
|
||||
dartIter=lcc.one_dart_per_incident_cell<2,3>(dh).begin();
|
||||
dartIter.cont(); ++dartIter)
|
||||
{
|
||||
// We draw the polygon
|
||||
|
||||
|
||||
// double r = (double)dartIter->attribute<3>()->info().r()/255.0;
|
||||
float r = (float)lcc.info<3>(dartIter).color().r()/255.0;
|
||||
float g = (float)lcc.info<3>(dartIter).color().g()/255.0;
|
||||
float b = (float)lcc.info<3>(dartIter).color().b()/255.0;
|
||||
double r = (double)lcc.info<3>(dartIter).color().r()/255.0;
|
||||
double g = (double)lcc.info<3>(dartIter).color().g()/255.0;
|
||||
double b = (double)lcc.info<3>(dartIter).color().b()/255.0;
|
||||
if ( !lcc.is_free(dartIter, 3) )
|
||||
{
|
||||
r += (float)lcc.info<3>(lcc.beta(dartIter,3)).color().r()/255.0;
|
||||
g += (float)lcc.info<3>(lcc.beta(dartIter,3)).color().g()/255.0;
|
||||
b += (float)lcc.info<3>(lcc.beta(dartIter,3)).color().b()/255.0;
|
||||
r += (double)lcc.info<3>(lcc.beta(dartIter,3)).color().r()/255.0;
|
||||
g += (double)lcc.info<3>(lcc.beta(dartIter,3)).color().g()/255.0;
|
||||
b += (double)lcc.info<3>(lcc.beta(dartIter,3)).color().b()/255.0;
|
||||
r /= 2; g /= 2; b /= 2;
|
||||
}
|
||||
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
//compute flat normals
|
||||
LCC::Vector normal = CGAL::compute_normal_of_cell_2(lcc,dartIter);
|
||||
normal = normal/(CGAL::sqrt(normal*normal));
|
||||
flat_normals.push_back(normal.x());flat_normals.push_back(normal.y());flat_normals.push_back(normal.z());
|
||||
flat_normals.push_back(normal.x());flat_normals.push_back(normal.y());flat_normals.push_back(normal.z());
|
||||
flat_normals.push_back(normal.x());flat_normals.push_back(normal.y());flat_normals.push_back(normal.z());
|
||||
|
||||
if (lcc.beta<1,1,1>(dartIter)!=dartIter)
|
||||
{
|
||||
P_traits cdt_traits(normal);
|
||||
CDT cdt(cdt_traits);
|
||||
|
||||
// Iterates on the vector of facet handles
|
||||
CDT::Vertex_handle previous = NULL, first = NULL;
|
||||
for (LCC::Dart_of_orbit_range<1>::const_iterator
|
||||
he_circ = lcc.darts_of_orbit<1>(dartIter).begin(),
|
||||
he_circ_end = lcc.darts_of_orbit<1>(dartIter).end();
|
||||
he_circ!=he_circ_end; ++he_circ)
|
||||
{
|
||||
CDT::Vertex_handle vh = cdt.insert(lcc.point(he_circ));
|
||||
if(first == NULL)
|
||||
{ first = vh; }
|
||||
//vh->info() = he_circ;
|
||||
if(previous!=NULL && previous != vh)
|
||||
{ cdt.insert_constraint(previous, vh); }
|
||||
previous = vh;
|
||||
}
|
||||
cdt.insert_constraint(previous, first);
|
||||
|
||||
// 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;
|
||||
}
|
||||
//check if the facet is external or internal
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//iterates on the internal faces to add the vertices to the positions
|
||||
//and the normals to the appropriate vectors
|
||||
for(CDT::Finite_faces_iterator ffit = cdt.finite_faces_begin(),
|
||||
ffitend = cdt.finite_faces_end(); ffit != ffitend; ++ffit)
|
||||
{
|
||||
if(!ffit->info().is_external)
|
||||
{
|
||||
smooth_normals.push_back(normal.x());
|
||||
smooth_normals.push_back(normal.y());
|
||||
smooth_normals.push_back(normal.z());
|
||||
|
||||
smooth_normals.push_back(normal.x());
|
||||
smooth_normals.push_back(normal.y());
|
||||
smooth_normals.push_back(normal.z());
|
||||
|
||||
smooth_normals.push_back(normal.x());
|
||||
smooth_normals.push_back(normal.y());
|
||||
smooth_normals.push_back(normal.z());
|
||||
|
||||
flat_normals.push_back(normal.x());
|
||||
flat_normals.push_back(normal.y());
|
||||
flat_normals.push_back(normal.z());
|
||||
|
||||
flat_normals.push_back(normal.x());
|
||||
flat_normals.push_back(normal.y());
|
||||
flat_normals.push_back(normal.z());
|
||||
|
||||
flat_normals.push_back(normal.x());
|
||||
flat_normals.push_back(normal.y());
|
||||
flat_normals.push_back(normal.z());
|
||||
|
||||
pos_facets.push_back(ffit->vertex(0)->point().x());
|
||||
pos_facets.push_back(ffit->vertex(0)->point().y());
|
||||
pos_facets.push_back(ffit->vertex(0)->point().z());
|
||||
|
||||
pos_facets.push_back(ffit->vertex(1)->point().x());
|
||||
pos_facets.push_back(ffit->vertex(1)->point().y());
|
||||
pos_facets.push_back(ffit->vertex(1)->point().z());
|
||||
|
||||
pos_facets.push_back(ffit->vertex(2)->point().x());
|
||||
pos_facets.push_back(ffit->vertex(2)->point().y());
|
||||
pos_facets.push_back(ffit->vertex(2)->point().z());
|
||||
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
colors.push_back(r);colors.push_back(g);colors.push_back(b);
|
||||
|
||||
flat_normals.push_back(normal.x());
|
||||
flat_normals.push_back(normal.y());
|
||||
flat_normals.push_back(normal.z());
|
||||
|
||||
flat_normals.push_back(normal.x());
|
||||
flat_normals.push_back(normal.y());
|
||||
flat_normals.push_back(normal.z());
|
||||
|
||||
flat_normals.push_back(normal.x());
|
||||
flat_normals.push_back(normal.y());
|
||||
flat_normals.push_back(normal.z());
|
||||
|
||||
for (LCC::Dart_of_orbit_range<1>::const_iterator
|
||||
orbitIter = lcc.darts_of_orbit<1>(dartIter).begin();
|
||||
|
|
@ -501,78 +440,54 @@ void Viewer::compute_elements()
|
|||
//compute Smooth normals
|
||||
LCC::Vector normal = CGAL::compute_normal_of_cell_0(lcc,orbitIter);
|
||||
normal = normal/(CGAL::sqrt(normal*normal));
|
||||
smooth_normals.push_back(normal.x());smooth_normals.push_back(normal.y());smooth_normals.push_back(normal.z());
|
||||
|
||||
smooth_normals.push_back(normal.x());
|
||||
smooth_normals.push_back(normal.y());
|
||||
smooth_normals.push_back(normal.z());
|
||||
|
||||
const LCC::Point& p = lcc.point(orbitIter);
|
||||
pos_facets.push_back(p.x()); pos_facets.push_back(p.y()); pos_facets.push_back(p.z());
|
||||
pos_facets.push_back(p.x());
|
||||
pos_facets.push_back(p.y());
|
||||
pos_facets.push_back(p.z());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
triangulate_facet();
|
||||
|
||||
//Edges
|
||||
{
|
||||
pos_lines.resize(0);
|
||||
void Viewer::compute_edges(Dart_handle dh)
|
||||
{
|
||||
LCC &lcc = *scene->lcc;
|
||||
|
||||
if ( !lcc.is_empty() )
|
||||
{
|
||||
|
||||
for (LCC::Attribute_range<3>::type::iterator
|
||||
it=lcc.attributes<3>().begin(),
|
||||
itend=lcc.attributes<3>().end(); it!=itend; ++it )
|
||||
{
|
||||
if ( it->info().is_visible() )
|
||||
{
|
||||
for(LCC::One_dart_per_incident_cell_range<1,3>::iterator
|
||||
dartIter=lcc.one_dart_per_incident_cell<1,3>
|
||||
(lcc.dart_of_attribute<3>(it)).begin(); dartIter.cont(); ++dartIter)
|
||||
dartIter=lcc.one_dart_per_incident_cell<1,3>(dh).begin();
|
||||
dartIter.cont(); ++dartIter)
|
||||
{
|
||||
const LCC::Point& p = lcc.point(dartIter);
|
||||
Dart_handle d2 = lcc.other_extremity(dartIter);
|
||||
if ( d2!=NULL )
|
||||
{
|
||||
const LCC::Point& p2 = lcc.point(d2);
|
||||
pos_lines.push_back(p.x()); pos_lines.push_back(p.y()); pos_lines.push_back(p.z());
|
||||
pos_lines.push_back(p2.x()); pos_lines.push_back(p2.y()); pos_lines.push_back(p2.z());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pos_lines.push_back(p.x());
|
||||
pos_lines.push_back(p.y());
|
||||
pos_lines.push_back(p.z());
|
||||
|
||||
pos_lines.push_back(p2.x());
|
||||
pos_lines.push_back(p2.y());
|
||||
pos_lines.push_back(p2.z());
|
||||
}
|
||||
}
|
||||
//Points
|
||||
{
|
||||
pos_points.resize(0);
|
||||
}
|
||||
|
||||
void Viewer::compute_vertices(Dart_handle dh, bool empty)
|
||||
{
|
||||
LCC &lcc = *scene->lcc;
|
||||
|
||||
if ( lcc.is_empty() )
|
||||
{
|
||||
bb = LCC::Point(CGAL::ORIGIN).bbox();
|
||||
bb = bb + LCC::Point(1,1,1).bbox(); // To avoid a warning from Qglviewer
|
||||
return;
|
||||
}
|
||||
|
||||
bool empty = true;
|
||||
for (LCC::Attribute_range<3>::type::iterator
|
||||
it=lcc.attributes<3>().begin(),
|
||||
itend=lcc.attributes<3>().end(); it!=itend; ++it )
|
||||
{
|
||||
if ( it->info().is_visible() )
|
||||
{
|
||||
for(LCC::One_dart_per_incident_cell_range<0,3>::iterator
|
||||
dartIter=lcc.one_dart_per_incident_cell<0,3>
|
||||
(lcc.dart_of_attribute<3>(it)).begin();
|
||||
dartIter=lcc.one_dart_per_incident_cell<0,3>(dh).begin();
|
||||
dartIter.cont(); ++dartIter)
|
||||
{
|
||||
const LCC::Point& p = lcc.point(dartIter);
|
||||
pos_points.push_back(p.x()); pos_points.push_back(p.y()); pos_points.push_back(p.z());
|
||||
pos_points.push_back(p.x());
|
||||
pos_points.push_back(p.y());
|
||||
pos_points.push_back(p.z());
|
||||
|
||||
if ( empty )
|
||||
{
|
||||
|
|
@ -582,18 +497,46 @@ void Viewer::compute_elements()
|
|||
else
|
||||
bb = bb + p.bbox();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Viewer::compute_elements()
|
||||
{
|
||||
LCC &lcc = *scene->lcc;
|
||||
|
||||
pos_facets.clear();
|
||||
flat_normals.clear();
|
||||
smooth_normals.clear();
|
||||
colors.clear();
|
||||
pos_lines.clear();
|
||||
pos_points.clear();
|
||||
|
||||
if ( lcc.is_empty() )
|
||||
{
|
||||
bb = LCC::Point(CGAL::ORIGIN).bbox();
|
||||
bb = bb + LCC::Point(1,1,1).bbox(); // To avoid a warning from Qglviewer
|
||||
return;
|
||||
}
|
||||
|
||||
bool empty = true;
|
||||
for (LCC::Attribute_range<3>::type::iterator it=lcc.attributes<3>().begin(),
|
||||
itend=lcc.attributes<3>().end(); it!=itend; ++it )
|
||||
{
|
||||
if ( it->info().is_visible() )
|
||||
{
|
||||
if (it->info().is_filled())
|
||||
compute_faces(lcc.dart_of_attribute<3>(it));
|
||||
|
||||
compute_edges(lcc.dart_of_attribute<3>(it));
|
||||
compute_vertices(lcc.dart_of_attribute<3>(it), empty);
|
||||
empty = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty )
|
||||
{
|
||||
bb = LCC::Point(CGAL::ORIGIN).bbox();
|
||||
bb = bb + LCC::Point(1,1,1).bbox(); // To avoid a warning from Qglviewer
|
||||
}
|
||||
}
|
||||
|
||||
void Viewer::attrib_buffers(QGLViewer* viewer)
|
||||
|
|
@ -612,21 +555,20 @@ void Viewer::attrib_buffers(QGLViewer* viewer)
|
|||
mvMatrix.data()[i] = (float)mat[i];
|
||||
}
|
||||
// define material
|
||||
QVector4D ambient(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
QVector4D ambient(0.4f, 0.4f, 0.4f, 0.4f);
|
||||
QVector4D diffuse( 0.9f,
|
||||
0.9f,
|
||||
0.9f,
|
||||
0.0f );
|
||||
0.9f );
|
||||
|
||||
QVector4D specular( 0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f );
|
||||
1.0f );
|
||||
|
||||
QVector4D position( 0.0f, -10.0f, -10.0f, 0.0f );
|
||||
QVector4D position( 10.0f, 10.0f, 10.0f, 0.0f );
|
||||
GLfloat shininess = 1.0f;
|
||||
|
||||
|
||||
rendering_program.bind();
|
||||
mvpLocation[0] = rendering_program.uniformLocation("mvp_matrix");
|
||||
mvLocation = rendering_program.uniformLocation("mv_matrix");
|
||||
|
|
@ -644,18 +586,15 @@ void Viewer::attrib_buffers(QGLViewer* viewer)
|
|||
rendering_program.setUniformValue(mvpLocation[0], mvpMatrix);
|
||||
rendering_program.setUniformValue(mvLocation, mvMatrix);
|
||||
|
||||
|
||||
rendering_program.release();
|
||||
rendering_program_p_l.bind();
|
||||
mvpLocation[1] = rendering_program_p_l.uniformLocation("mvp_matrix");
|
||||
colorLocation = rendering_program_p_l.uniformLocation("color");
|
||||
rendering_program.setUniformValue(mvpLocation[1], mvpMatrix);
|
||||
rendering_program_p_l.release();
|
||||
are_buffers_initialized = true;
|
||||
}
|
||||
|
||||
void
|
||||
Viewer::sceneChanged()
|
||||
void Viewer::sceneChanged()
|
||||
{
|
||||
compute_elements();
|
||||
this->camera()->setSceneBoundingBox(qglviewer::Vec(bb.xmin(),
|
||||
|
|
@ -665,22 +604,26 @@ Viewer::sceneChanged()
|
|||
bb.ymax(),
|
||||
bb.zmax()));
|
||||
are_buffers_initialized = false;
|
||||
|
||||
if (m_previous_scene_empty)
|
||||
this->showEntireScene();
|
||||
else
|
||||
this->updateGL();
|
||||
|
||||
m_previous_scene_empty = scene->lcc->is_empty(); // for the next call to sceneChanged
|
||||
}
|
||||
|
||||
void Viewer::draw()
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
if(!are_buffers_initialized)
|
||||
if(!are_buffers_initialized)
|
||||
initialize_buffers();
|
||||
|
||||
|
||||
QColor color;
|
||||
QColor color;
|
||||
if ( !wireframe )
|
||||
{
|
||||
if(flatShading)
|
||||
{
|
||||
|
||||
vao[0].bind();
|
||||
attrib_buffers(this);
|
||||
rendering_program.bind();
|
||||
|
|
@ -748,7 +691,6 @@ void Viewer::init()
|
|||
::glEnable(GL_LIGHTING);
|
||||
|
||||
::glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
|
||||
// ::glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
|
||||
|
||||
if (flatShading)
|
||||
{
|
||||
|
|
@ -776,7 +718,6 @@ void Viewer::keyPressEvent(QKeyEvent *e)
|
|||
{
|
||||
const Qt::KeyboardModifiers modifiers = e->modifiers();
|
||||
|
||||
bool handled = false;
|
||||
if ((e->key()==Qt::Key_W) && (modifiers==Qt::NoButton))
|
||||
{
|
||||
wireframe = !wireframe;
|
||||
|
|
@ -784,7 +725,6 @@ void Viewer::keyPressEvent(QKeyEvent *e)
|
|||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
else
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
handled = true;
|
||||
updateGL();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_F) && (modifiers==Qt::NoButton))
|
||||
|
|
@ -808,23 +748,19 @@ void Viewer::keyPressEvent(QKeyEvent *e)
|
|||
::glBlendFunc(GL_ONE, GL_ZERO);
|
||||
::glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
|
||||
}
|
||||
handled = true;
|
||||
updateGL();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_E) && (modifiers==Qt::NoButton))
|
||||
{
|
||||
edges = !edges;
|
||||
handled = true;
|
||||
updateGL();
|
||||
}
|
||||
else if ((e->key()==Qt::Key_V) && (modifiers==Qt::NoButton))
|
||||
{
|
||||
vertices = !vertices;
|
||||
handled = true;
|
||||
updateGL();
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
else
|
||||
QGLViewer::keyPressEvent(e);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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,11 +103,50 @@ 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:
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue