mirror of https://github.com/CGAL/cgal
Improve method
This commit is contained in:
parent
cc0e26f4b1
commit
b848314336
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright (c) 2017 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$
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
//
|
||||
// Author(s) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
|
||||
//
|
||||
#ifndef CGAL_CREATION_OF_TEST_CASES_FOR_PATHS_H
|
||||
#define CGAL_CREATION_OF_TEST_CASES_FOR_PATHS_H 1
|
||||
|
||||
#include<CGAL/Path_generators.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template<typename Path>
|
||||
void generate_one_positive_spur(Path& p)
|
||||
{
|
||||
p.clear();
|
||||
p.push_back(p.get_map().darts().iterator_to(p.get_map().darts()[5])); // 6th dart of the map
|
||||
extend_straight_positive(p, 6);
|
||||
extend_uturn_positive(p);
|
||||
extend_uturn_half_turn(p);
|
||||
extend_straight_positive(p, 4);
|
||||
}
|
||||
|
||||
template<typename Path>
|
||||
void generate_one_negative_spur(Path& p)
|
||||
{
|
||||
p.clear();
|
||||
p.push_back(p.get_map().darts().iterator_to(p.get_map().darts()[5])); // 6th dart of the map
|
||||
extend_straight_negative(p, 6);
|
||||
extend_uturn_negative(p);
|
||||
extend_uturn_half_turn(p);
|
||||
extend_straight_negative(p, 4);
|
||||
}
|
||||
|
||||
template<typename Path>
|
||||
void generate_cyclic_spur(Path& p)
|
||||
{
|
||||
p.clear();
|
||||
p.push_back(p.get_map().darts().iterator_to(p.get_map().darts()[5])); // 6th dart of the map
|
||||
extend_uturn_half_turn(p);
|
||||
}
|
||||
|
||||
template<typename Path>
|
||||
void generate_one_positive_bracket(Path& p)
|
||||
{
|
||||
p.clear();
|
||||
p.push_back(p.get_map().darts().iterator_to(p.get_map().darts()[5])); // 6th dart of the map
|
||||
extend_straight_positive(p, 3);
|
||||
extend_uturn_negative(p);
|
||||
extend_uturn_positive(p);
|
||||
extend_straight_positive(p, 6);
|
||||
extend_uturn_positive(p);
|
||||
extend_uturn_negative(p);
|
||||
extend_straight_positive(p, 2);
|
||||
}
|
||||
|
||||
template<typename Path>
|
||||
void generate_one_negative_bracket(Path& p)
|
||||
{
|
||||
p.clear();
|
||||
p.push_back(p.get_map().darts().iterator_to(p.get_map().darts()[5])); // 6th dart of the map
|
||||
extend_straight_negative(p, 3);
|
||||
extend_uturn_positive(p);
|
||||
extend_uturn_negative(p);
|
||||
extend_straight_negative(p, 6);
|
||||
extend_uturn_negative(p);
|
||||
extend_uturn_positive(p);
|
||||
extend_straight_negative(p, 2);
|
||||
}
|
||||
|
||||
template<typename Path>
|
||||
void generate_positive_bracket_special1(Path& p)
|
||||
{ // Case (x, 1, 2^r, 1)
|
||||
p.clear();
|
||||
// p.push_back(p.get_map().template beta<2>(p.get_map().darts().iterator_to(p.get_map().darts()[5]))); // 6th dart of the map
|
||||
p.push_back(p.get_map().darts().iterator_to(p.get_map().darts()[12])); // 6th dart of the map
|
||||
extend_uturn_positive(p, 4);
|
||||
extend_straight_positive(p, 1);
|
||||
/*extend_uturn_positive(p);
|
||||
extend_straight_positive(p, 1);
|
||||
extend_straight_positive(p, 8);*/
|
||||
//extend_uturn_negative(p);
|
||||
}
|
||||
|
||||
|
||||
} // namespace CGAL
|
||||
|
||||
#endif // CGAL_CREATION_OF_TEST_CASES_FOR_PATHS_H //
|
||||
// EOF //
|
||||
|
|
@ -102,7 +102,7 @@ bool extend_path_randomly(Path& p, bool allow_half_turn=false)
|
|||
template<typename Path>
|
||||
void extend_straight_positive(Path& p, std::size_t nb=1)
|
||||
{
|
||||
if (p.is_empty())
|
||||
if (p.is_empty() || nb==0)
|
||||
{ return; }
|
||||
|
||||
for (std::size_t i=0; i<nb; ++i)
|
||||
|
|
@ -116,7 +116,7 @@ void extend_straight_positive(Path& p, std::size_t nb=1)
|
|||
template<typename Path>
|
||||
void extend_straight_negative(Path& p, std::size_t nb=1)
|
||||
{
|
||||
if (p.is_empty())
|
||||
if (p.is_empty() || nb==0)
|
||||
{ return; }
|
||||
|
||||
for (std::size_t i=0; i<nb; ++i)
|
||||
|
|
@ -128,28 +128,45 @@ void extend_straight_negative(Path& p, std::size_t nb=1)
|
|||
}
|
||||
|
||||
template<typename Path>
|
||||
void extend_uturn_positive(Path& p)
|
||||
void extend_uturn_positive(Path& p, std::size_t nb=1)
|
||||
{
|
||||
if (p.is_empty())
|
||||
if (p.is_empty() || nb==0)
|
||||
{ return; }
|
||||
|
||||
|
||||
typename Path::Dart_const_handle d2=p.get_map().template beta<1>(p.back());
|
||||
for (std::size_t i=1; i<nb; ++i)
|
||||
{ d2=p.get_map().template beta<2, 1>(d2); }
|
||||
|
||||
if (d2!=p.get_map().null_dart_handle)
|
||||
{ p.push_back(d2); }
|
||||
}
|
||||
|
||||
template<typename Path>
|
||||
void extend_uturn_negative(Path& p)
|
||||
void extend_uturn_negative(Path& p, std::size_t nb=1)
|
||||
{
|
||||
if (p.is_empty())
|
||||
{ return; }
|
||||
|
||||
typename Path::Dart_const_handle d2=p.get_map().template beta<2,0,2>(p.back());
|
||||
typename Path::Dart_const_handle d2=p.get_map().template beta<2>(p.back());
|
||||
for (std::size_t i=0; i<nb; ++i)
|
||||
{ d2=p.get_map().template beta<0, 2>(d2); }
|
||||
|
||||
if (d2!=p.get_map().null_dart_handle)
|
||||
{ p.push_back(d2); }
|
||||
}
|
||||
|
||||
template<typename Path>
|
||||
template<typename Path>
|
||||
void extend_uturn_half_turn(Path& p)
|
||||
{
|
||||
if (p.is_empty())
|
||||
{ return; }
|
||||
|
||||
typename Path::Dart_const_handle d2=p.get_map().template beta<2>(p.back());
|
||||
if (d2!=p.get_map().null_dart_handle)
|
||||
{ p.push_back(d2); }
|
||||
}
|
||||
|
||||
template<typename Path>
|
||||
void create_braket_positive(Path& p, std::size_t length, CGAL::Random& random)
|
||||
{
|
||||
if (p.is_empty())
|
||||
|
|
|
|||
|
|
@ -259,6 +259,8 @@ public:
|
|||
|
||||
bool bracket_flattening_one_step()
|
||||
{
|
||||
if (is_empty()) return false;
|
||||
|
||||
bool res=false;
|
||||
std::vector<Dart_const_handle> new_path;
|
||||
std::size_t i;
|
||||
|
|
@ -312,6 +314,8 @@ public:
|
|||
|
||||
bool remove_spurs_one_step()
|
||||
{
|
||||
if (is_empty()) return false;
|
||||
|
||||
bool res=false;
|
||||
std::size_t i;
|
||||
std::vector<Dart_const_handle> new_path;
|
||||
|
|
@ -328,6 +332,9 @@ public:
|
|||
++i;
|
||||
}
|
||||
}
|
||||
if (i==m_path.size()-1)
|
||||
{ new_path.push_back(m_path[m_path.size()-1]); }
|
||||
|
||||
new_path.swap(m_path);
|
||||
return res;
|
||||
}
|
||||
|
|
@ -344,15 +351,21 @@ public:
|
|||
{
|
||||
assert(next_turn(begin)!=2);
|
||||
std::size_t end=begin+1;
|
||||
if (end==m_path.size()-1)
|
||||
if (end==m_path.size()-1 && !is_closed())
|
||||
{ return begin; } // begin is the before last dart
|
||||
|
||||
while (next_turn(end)==2)
|
||||
while (next_turn(end)==2 && end!=begin)
|
||||
{
|
||||
++end;
|
||||
if (is_closed() && end==m_path.size()) { end=0; }
|
||||
}
|
||||
|
||||
if (begin==end)
|
||||
{ // Case of a path having only 2 turns
|
||||
// TODO SOMETHING
|
||||
std::cout<<"TODO TODO !!"<<std::endl;
|
||||
}
|
||||
|
||||
if (next_turn(end)==1)
|
||||
{
|
||||
++end;
|
||||
|
|
@ -361,16 +374,12 @@ public:
|
|||
else
|
||||
{ return begin; }
|
||||
|
||||
// TODO
|
||||
/* if ((positive && next_turn(end)==1) ||
|
||||
(!positive && next_negative_turn(end)==1)) // We are on the end of a bracket
|
||||
while (next_turn(end)==2)
|
||||
{
|
||||
++end;
|
||||
if (is_closed() && end==m_path.size()) { end=0; }
|
||||
}
|
||||
else
|
||||
{ end=begin; }
|
||||
*/
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,57 @@
|
|||
|
||||
#include <CGAL/Path_generators.h>
|
||||
#include <CGAL/Path_on_surface.h>
|
||||
#include <CGAL/Creation_of_test_cases_for_paths.h>
|
||||
|
||||
typedef CGAL::Linear_cell_complex_for_combinatorial_map<2,3> LCC_3_cmap;
|
||||
typedef CGAL::Linear_cell_complex_for_generalized_map<2,3> LCC_3_gmap;
|
||||
|
||||
void simplify_path(CGAL::Path_on_surface<LCC_3_cmap>& path,
|
||||
bool draw=false)
|
||||
{
|
||||
std::vector<const CGAL::Path_on_surface<LCC_3_cmap>*> v;
|
||||
if (draw)
|
||||
{
|
||||
v.push_back(&path);
|
||||
display(path.get_map(), v);
|
||||
}
|
||||
|
||||
CGAL::Path_on_surface<LCC_3_cmap>* prevp=&path;
|
||||
CGAL::Path_on_surface<LCC_3_cmap>* curp=NULL;
|
||||
do
|
||||
{
|
||||
curp=new CGAL::Path_on_surface<LCC_3_cmap>(*prevp);
|
||||
if (curp->bracket_flattening_one_step())
|
||||
{
|
||||
if (draw) { v.push_back(curp); }
|
||||
prevp=curp;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete curp;
|
||||
curp=NULL;
|
||||
}
|
||||
// if (nbtest==1)
|
||||
// display(lcc, v);
|
||||
}
|
||||
while(curp!=NULL);
|
||||
|
||||
curp=new CGAL::Path_on_surface<LCC_3_cmap>(*prevp);
|
||||
if (curp->remove_spurs())
|
||||
{
|
||||
if (draw) { v.push_back(curp); }
|
||||
prevp=curp;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete curp;
|
||||
curp=NULL;
|
||||
}
|
||||
|
||||
if (draw)
|
||||
{ display(path.get_map(), v); }
|
||||
}
|
||||
|
||||
void test_file(int argc, char** argv)
|
||||
{
|
||||
if (argc!=2)
|
||||
|
|
@ -60,14 +107,14 @@ void test_file(int argc, char** argv)
|
|||
pp1=cmt.transform_original_path_into_quad_surface(p1);
|
||||
|
||||
std::cout<<"Original path has "<<pp1.length()<<" darts."<<std::endl;
|
||||
pp1.bracket_flattening();
|
||||
simplify_path(pp1, false);
|
||||
std::cout<<"After bracket flattening, the path has "<<pp1.length()<<" darts."<<std::endl;
|
||||
}
|
||||
|
||||
void test_simplify_path(const LCC_3_cmap& lcc,
|
||||
std::size_t nb1, std::size_t nb2, std::size_t nb3,
|
||||
CGAL::Random& random,
|
||||
bool draw=false)
|
||||
void test_simplify_random_path(const LCC_3_cmap& lcc,
|
||||
std::size_t nb1, std::size_t nb2, std::size_t nb3,
|
||||
CGAL::Random& random,
|
||||
bool draw=false)
|
||||
{
|
||||
static std::size_t nbtest=0;
|
||||
std::cout<<"[BEGIN] TEST "<<nbtest<<"."<<std::endl;
|
||||
|
|
@ -79,49 +126,12 @@ void test_simplify_path(const LCC_3_cmap& lcc,
|
|||
CGAL::extend_straight_positive(path, nb3);
|
||||
CGAL::generate_random_path(path, random.get_int(0, 15), random);
|
||||
|
||||
std::vector<const CGAL::Path_on_surface<LCC_3_cmap>*> v;
|
||||
v.push_back(&path);
|
||||
// display(lcc, v);
|
||||
|
||||
CGAL::Path_on_surface<LCC_3_cmap>* prevp=&path;
|
||||
CGAL::Path_on_surface<LCC_3_cmap>* curp=NULL;
|
||||
do
|
||||
{
|
||||
curp=new CGAL::Path_on_surface<LCC_3_cmap>(*prevp);
|
||||
if (curp->bracket_flattening_one_step())
|
||||
{
|
||||
v.push_back(curp);
|
||||
prevp=curp;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete curp;
|
||||
curp=NULL;
|
||||
}
|
||||
// if (nbtest==1)
|
||||
// display(lcc, v);
|
||||
}
|
||||
while(curp!=NULL);
|
||||
|
||||
curp=new CGAL::Path_on_surface<LCC_3_cmap>(*prevp);
|
||||
if (curp->remove_spurs())
|
||||
{
|
||||
v.push_back(curp);
|
||||
prevp=curp;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete curp;
|
||||
curp=NULL;
|
||||
}
|
||||
|
||||
if (draw)
|
||||
{ display(lcc, v); }
|
||||
simplify_path(path, draw);
|
||||
|
||||
std::cout<<"[END] TEST "<<nbtest++<<"."<<std::endl;
|
||||
}
|
||||
|
||||
void test_square()
|
||||
void test_some_random_paths_on_cube()
|
||||
{
|
||||
LCC_3_cmap lcc;
|
||||
if (!CGAL::load_off(lcc, "./cube-mesh-5-5.off"))
|
||||
|
|
@ -137,22 +147,67 @@ void test_square()
|
|||
CGAL::Random random(1); // fix seed
|
||||
|
||||
// path 1: 2 straight darts to begin; 1 + turn; 6 straight; 1 + turn; 3 straight
|
||||
test_simplify_path(lcc, 2, 6, 3, random, true);
|
||||
test_simplify_random_path(lcc, 2, 6, 3, random, true);
|
||||
|
||||
// path 2: 3 straight darts to begin; 1 + turn; 8 straight; 1 + turn; 4 straight
|
||||
test_simplify_path(lcc, 3, 8, 4, random, true);
|
||||
test_simplify_random_path(lcc, 3, 8, 4, random, true);
|
||||
|
||||
// path 3: 5 straight darts to begin; 1 + turn; 12 straight; 1 + turn; 8 straight
|
||||
test_simplify_path(lcc, 5, 12, 8, random, true);
|
||||
test_simplify_random_path(lcc, 5, 12, 8, random, true);
|
||||
|
||||
// path 4: 5 straight darts to begin; 1 + turn; 12 straight; 1 + turn; 8 straight
|
||||
test_simplify_path(lcc, 5, 12, 8, random, true);
|
||||
test_simplify_random_path(lcc, 5, 12, 8, random, true);
|
||||
}
|
||||
|
||||
void test_all_cases_spurs_and_bracket()
|
||||
{
|
||||
LCC_3_cmap lcc1;
|
||||
if (!CGAL::load_off(lcc1, "./cube-mesh-5-5.off"))
|
||||
{
|
||||
std::cout<<"PROBLEM reading file ./cube-mesh-5-5.off"<<std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
LCC_3_cmap lcc2;
|
||||
if (!CGAL::load_off(lcc2, "./spiral-squared.off"))
|
||||
{
|
||||
std::cout<<"PROBLEM reading file ./spiral-squared.off"<<std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
lcc2.reverse_orientation();
|
||||
/* std::cout<<"Initial map 1: ";
|
||||
lcc.display_characteristics(std::cout) << ", valid="
|
||||
<< lcc.is_valid() << std::endl;
|
||||
*/
|
||||
|
||||
CGAL::Path_on_surface<LCC_3_cmap> path1(lcc1);
|
||||
|
||||
generate_one_positive_spur(path1);
|
||||
simplify_path(path1, false);
|
||||
|
||||
generate_one_negative_spur(path1);
|
||||
simplify_path(path1, false);
|
||||
|
||||
generate_cyclic_spur(path1);
|
||||
simplify_path(path1, false);
|
||||
|
||||
generate_one_positive_bracket(path1);
|
||||
simplify_path(path1, false);
|
||||
|
||||
generate_one_negative_bracket(path1);
|
||||
simplify_path(path1, false);
|
||||
|
||||
CGAL::Path_on_surface<LCC_3_cmap> path2(lcc2);
|
||||
|
||||
generate_positive_bracket_special1(path2);
|
||||
simplify_path(path2, true);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// test_file(argc, argv);
|
||||
test_square();
|
||||
|
||||
// test_some_random_paths_on_cube();
|
||||
test_all_cases_spurs_and_bracket();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ public:
|
|||
lcc(alcc),
|
||||
m_paths(paths),
|
||||
m_current_path(m_paths.size()),
|
||||
m_current_dart(alcc.number_of_darts()),
|
||||
m_nofaces(anofaces),
|
||||
m_fcolor(fcolor)
|
||||
{ compute_elements(); }
|
||||
|
|
@ -106,35 +107,55 @@ protected:
|
|||
unsigned int markedges = lcc.get_new_mark();
|
||||
unsigned int markvertices = lcc.get_new_mark();
|
||||
|
||||
if (m_current_path==m_paths.size())
|
||||
{
|
||||
for (unsigned int i=0; i<m_paths.size(); ++i)
|
||||
{ compute_path(i, markedges); }
|
||||
if (m_current_dart!=lcc.number_of_darts())
|
||||
{ // We want to draw only one dart
|
||||
Dart_const_handle selected_dart=lcc.darts().iterator_to(lcc.darts()[m_current_dart]);
|
||||
compute_edge(selected_dart, CGAL::Color(255,0,0));
|
||||
CGAL::mark_cell<LCC, 1>(lcc, selected_dart, markedges);
|
||||
compute_vertex(selected_dart);
|
||||
|
||||
for (typename LCC::Dart_range::const_iterator it=lcc.darts().begin(),
|
||||
itend=lcc.darts().end(); it!=itend; ++it )
|
||||
{
|
||||
if ( !lcc.is_marked(it, markedges) )
|
||||
{
|
||||
compute_edge(it);
|
||||
CGAL::mark_cell<LCC, 1>(lcc, it, markedges);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
compute_path(m_current_path, markedges);
|
||||
}
|
||||
|
||||
for (typename LCC::Dart_range::const_iterator it=lcc.darts().begin(),
|
||||
itend=lcc.darts().end(); it!=itend; ++it )
|
||||
{
|
||||
if ( !m_nofaces && !lcc.is_marked(it, markfaces) )
|
||||
if (m_current_path==m_paths.size())
|
||||
{
|
||||
compute_face(it);
|
||||
CGAL::mark_cell<LCC, 2>(lcc, it, markfaces);
|
||||
for (unsigned int i=0; i<m_paths.size(); ++i)
|
||||
{ compute_path(i, markedges); }
|
||||
}
|
||||
else
|
||||
{
|
||||
compute_path(m_current_path, markedges);
|
||||
}
|
||||
|
||||
if ( !lcc.is_marked(it, markedges) )
|
||||
for (typename LCC::Dart_range::const_iterator it=lcc.darts().begin(),
|
||||
itend=lcc.darts().end(); it!=itend; ++it )
|
||||
{
|
||||
compute_edge(it);
|
||||
CGAL::mark_cell<LCC, 1>(lcc, it, markedges);
|
||||
}
|
||||
if ( !m_nofaces && !lcc.is_marked(it, markfaces) )
|
||||
{
|
||||
compute_face(it);
|
||||
CGAL::mark_cell<LCC, 2>(lcc, it, markfaces);
|
||||
}
|
||||
|
||||
if ( !lcc.is_marked(it, markvertices) )
|
||||
{
|
||||
compute_vertex(it);
|
||||
CGAL::mark_cell<LCC, 0>(lcc, it, markvertices);
|
||||
if ( !lcc.is_marked(it, markedges) )
|
||||
{
|
||||
compute_edge(it);
|
||||
CGAL::mark_cell<LCC, 1>(lcc, it, markedges);
|
||||
}
|
||||
|
||||
if ( !lcc.is_marked(it, markvertices) )
|
||||
{
|
||||
compute_vertex(it);
|
||||
CGAL::mark_cell<LCC, 0>(lcc, it, markvertices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -196,7 +217,30 @@ protected:
|
|||
if ((e->key()==::Qt::Key_N) && (modifiers==::Qt::NoButton))
|
||||
{
|
||||
m_current_path=(m_current_path+1)%(m_paths.size()+1);
|
||||
displayMessage(QString("Draw path=%1.").arg((m_current_path)));
|
||||
if (m_current_path==m_paths.size())
|
||||
{
|
||||
displayMessage(QString("Draw all paths."));
|
||||
}
|
||||
else
|
||||
{
|
||||
displayMessage(QString("Draw path=%1.").arg((m_current_path)));
|
||||
}
|
||||
compute_elements();
|
||||
initialize_buffers();
|
||||
compile_shaders();
|
||||
updateGL();
|
||||
}
|
||||
else if ((e->key()==::Qt::Key_D) && (modifiers==::Qt::NoButton))
|
||||
{
|
||||
m_current_dart=(m_current_dart+1)%(lcc.number_of_darts()+1);
|
||||
if (m_current_dart==lcc.number_of_darts())
|
||||
{
|
||||
displayMessage(QString("Draw all darts."));
|
||||
}
|
||||
else
|
||||
{
|
||||
displayMessage(QString("Draw dart=%1.").arg((m_current_dart)));
|
||||
}
|
||||
compute_elements();
|
||||
initialize_buffers();
|
||||
compile_shaders();
|
||||
|
|
@ -227,6 +271,7 @@ protected:
|
|||
const ColorFunctor& m_fcolor;
|
||||
const std::vector<const Path_on_surface<LCC>*>& m_paths;
|
||||
unsigned int m_current_path;
|
||||
unsigned int m_current_dart;
|
||||
};
|
||||
|
||||
template<class LCC, class ColorFunctor>
|
||||
|
|
|
|||
Loading…
Reference in New Issue