mirror of https://github.com/CGAL/cgal
Merge pull request #3293 from maxGimeno/Demo-Mesh_engraving-GF
Polyhedron Demo: Mesh Engraving Plugin
This commit is contained in:
commit
5b1e535cb9
|
|
@ -109,6 +109,9 @@ target_link_libraries(random_perturbation_plugin PUBLIC scene_surface_mesh_item
|
|||
polyhedron_demo_plugin(degenerated_faces_plugin Degenerated_faces_plugin)
|
||||
target_link_libraries(degenerated_faces_plugin PUBLIC scene_surface_mesh_item scene_selection_item)
|
||||
|
||||
qt5_wrap_ui( engravUI_FILES Engrave_dock_widget.ui )
|
||||
polyhedron_demo_plugin(engrave_text_plugin Engrave_text_plugin ${engravUI_FILES})
|
||||
target_link_libraries(engrave_text_plugin PUBLIC scene_surface_mesh_item scene_selection_item scene_polylines_item)
|
||||
|
||||
polyhedron_demo_plugin(extrude_plugin Extrude_plugin)
|
||||
target_link_libraries(extrude_plugin PUBLIC scene_surface_mesh_item scene_selection_item)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,316 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EngraveWidget</class>
|
||||
<widget class="QDockWidget" name="EngraveWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>293</width>
|
||||
<height>515</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Engraving</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLineEdit" name="lineEdit">
|
||||
<property name="placeholderText">
|
||||
<string>An Example Text</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="visualizeButton">
|
||||
<property name="text">
|
||||
<string>Visualize</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="engraveButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Engrave</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="text_meshButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Generate Text Mesh</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="reset_button">
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,0,0,0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="t_up_pushButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../Polyhedron_3.qrc">
|
||||
<normaloff>:/cgal/icons/resources/up.png</normaloff>:/cgal/icons/resources/up.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<widget class="QSlider" name="rot_slider">
|
||||
<property name="minimum">
|
||||
<number>-179</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>179</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="t_right_pushButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../Polyhedron_3.qrc">
|
||||
<normaloff>:/cgal/icons/resources/right_arrow.png</normaloff>:/cgal/icons/resources/right_arrow.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="t_down_pushButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../Polyhedron_3.qrc">
|
||||
<normaloff>:/cgal/icons/resources/down.png</normaloff>:/cgal/icons/resources/down.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Scaling factor in X:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="t_left_pushButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../Polyhedron_3.qrc">
|
||||
<normaloff>:/cgal/icons/resources/left_arrow.png</normaloff>:/cgal/icons/resources/left_arrow.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Rotation degree:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QSlider" name="scalX_slider">
|
||||
<property name="maximum">
|
||||
<number>2000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="sliderPosition">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QSlider" name="scalY_slider">
|
||||
<property name="maximum">
|
||||
<number>2000</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Scaling factor in Y:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="3">
|
||||
<widget class="QSlider" name="text_prec_slider">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Text Precision</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QGraphicsView" name="graphicsView"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Engraving Depth</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="1">
|
||||
<widget class="QSlider" name="bot_slider">
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSlider" name="top_slider">
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Inside depth:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Outside depth:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="letter_checkBox">
|
||||
<property name="text">
|
||||
<string>Uniform letter mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../Polyhedron_3.qrc"/>
|
||||
<include location="../../Polyhedron_3.qrc"/>
|
||||
<include location="../../Polyhedron_3.qrc"/>
|
||||
<include location="../../Polyhedron_3.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -0,0 +1,931 @@
|
|||
//General Plugin Data
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_helper.h>
|
||||
#include <CGAL/Three/Three.h>
|
||||
|
||||
#include "ui_Engrave_dock_widget.h"
|
||||
//Items
|
||||
#include "Scene_surface_mesh_item.h"
|
||||
#include "Scene_polyhedron_selection_item.h"
|
||||
#include "Scene_polylines_item.h"
|
||||
#include "Messages_interface.h"
|
||||
|
||||
#include <CGAL/Surface_mesh_parameterization/Error_code.h>
|
||||
#include <CGAL/surface_mesh_parameterization.h>
|
||||
#include <CGAL/Polygon_mesh_processing/bbox.h>
|
||||
#include <CGAL/Polygon_mesh_processing/extrude.h>
|
||||
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
|
||||
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
|
||||
#include <CGAL/Polygon_mesh_processing/corefinement.h>
|
||||
#include <CGAL/Polygon_mesh_processing/self_intersections.h>
|
||||
#include <CGAL/Surface_mesh_shortest_path.h>
|
||||
#include <CGAL/double.h>
|
||||
#include <CGAL/AABB_tree.h>
|
||||
#include <CGAL/AABB_traits.h>
|
||||
#include <CGAL/AABB_face_graph_triangle_primitive.h>
|
||||
#include <CGAL/Triangulation_face_base_with_info_2.h>
|
||||
#include <CGAL/Projection_traits_xy_3.h>
|
||||
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
|
||||
|
||||
#include <CGAL/linear_least_squares_fitting_2.h>
|
||||
#include <CGAL/Polygon_mesh_processing/measure.h>
|
||||
#include <CGAL/centroid.h>
|
||||
|
||||
#include <CGAL/boost/graph/Face_filtered_graph.h>
|
||||
|
||||
#include <QPainterPath>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsItem>
|
||||
#include <QDialog>
|
||||
|
||||
#include <CGAL/Qt/GraphicsViewNavigation.h>
|
||||
|
||||
using namespace CGAL::Three;
|
||||
namespace SMP = CGAL::Surface_mesh_parameterization;
|
||||
typedef EPICK::Point_2 Point_2;
|
||||
typedef EPICK::Point_3 Point_3;
|
||||
|
||||
typedef boost::graph_traits<SMesh>::
|
||||
edge_descriptor edge_descriptor;
|
||||
typedef boost::graph_traits<SMesh>::
|
||||
halfedge_descriptor halfedge_descriptor;
|
||||
typedef boost::graph_traits<SMesh>::
|
||||
vertex_descriptor vertex_descriptor;
|
||||
|
||||
typedef boost::unordered_set<boost::graph_traits<SMesh>::
|
||||
face_descriptor> Component;
|
||||
|
||||
struct FaceInfo2
|
||||
{
|
||||
FaceInfo2(){}
|
||||
int nesting_level;
|
||||
bool in_domain(){
|
||||
return nesting_level%2 == 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PMAP,
|
||||
typename NMAP>
|
||||
struct Bot
|
||||
{
|
||||
Bot(NMAP nmap,
|
||||
double d,
|
||||
PMAP pmap):d(d),
|
||||
pmap(pmap),
|
||||
nmap(nmap){}
|
||||
template<typename VD, typename T>
|
||||
void operator()(const T& v1,VD v2) const
|
||||
{
|
||||
put(pmap, v2, get(pmap, v2)-d*get(nmap, v1));
|
||||
}
|
||||
double d;
|
||||
PMAP pmap;
|
||||
NMAP nmap;
|
||||
|
||||
};
|
||||
|
||||
template<typename PMAP,
|
||||
typename NMAP>
|
||||
struct Top
|
||||
{
|
||||
Top(NMAP nmap,
|
||||
PMAP pmap,
|
||||
double d):d(d),
|
||||
nmap(nmap),
|
||||
pmap(pmap){}
|
||||
|
||||
template<typename VD, typename T>
|
||||
void operator()(const T& v1, VD v2) const
|
||||
{
|
||||
put(pmap, v2, get(pmap, v2)+d*get(nmap, v1));
|
||||
}
|
||||
double d;
|
||||
NMAP nmap;
|
||||
PMAP pmap;
|
||||
};
|
||||
|
||||
typedef EPICK Gt;
|
||||
typedef CGAL::Triangulation_vertex_base_2<Gt> Vb;
|
||||
typedef CGAL::Triangulation_face_base_with_info_2<FaceInfo2,Gt > Fbb;
|
||||
typedef CGAL::Constrained_triangulation_face_base_2<Gt,Fbb> Fb;
|
||||
typedef CGAL::Triangulation_data_structure_2<Vb, Fb> TDS;
|
||||
typedef CGAL::No_intersection_tag Tag;
|
||||
typedef CGAL::Constrained_Delaunay_triangulation_2<Gt, TDS, Tag> CDT;
|
||||
|
||||
//Parameterization and text displaying
|
||||
class ParamItem : public QGraphicsItem
|
||||
{
|
||||
public :
|
||||
ParamItem(Component* component,
|
||||
const std::vector<std::vector<EPICK::Point_2> > &polylines,
|
||||
EPICK::Aff_transformation_2 transfo,
|
||||
SMesh* graph,
|
||||
QRectF brect)
|
||||
:
|
||||
QGraphicsItem(),
|
||||
bounding_rect(brect),
|
||||
component(component),
|
||||
polylines(polylines),
|
||||
graph(graph),
|
||||
transfo(transfo){}
|
||||
|
||||
~ParamItem()
|
||||
{
|
||||
delete component;
|
||||
}
|
||||
|
||||
QRectF boundingRect() const
|
||||
{
|
||||
return bounding_rect;
|
||||
}
|
||||
|
||||
void set_transfo(EPICK::Aff_transformation_2 t){ transfo = t;}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
|
||||
{
|
||||
QPen pen;
|
||||
QBrush brush;
|
||||
brush.setColor(QColor(100, 100, 255));
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
pen.setColor(Qt::black);
|
||||
pen.setWidth(0);
|
||||
painter->setPen(pen);
|
||||
painter->setBrush(brush);
|
||||
SMesh::Property_map<halfedge_descriptor,std::pair<float, float> > uv;
|
||||
uv = graph->add_property_map<halfedge_descriptor,std::pair<float, float> >
|
||||
("h:uv",std::make_pair(0.0f,0.0f)).first;
|
||||
for( Component::iterator
|
||||
fi = component->begin();
|
||||
fi != component->end();
|
||||
++fi)
|
||||
{
|
||||
boost::graph_traits<SMesh>::face_descriptor f(*fi);
|
||||
QPointF points[3];
|
||||
boost::graph_traits<SMesh>::halfedge_descriptor h = halfedge(f, *graph);;
|
||||
points[0] = QPointF(get(uv, h).first, -get(uv, h).second);
|
||||
h = next(halfedge(f, *graph), *graph);
|
||||
points[1] = QPointF(get(uv, h).first, -get(uv, h).second);
|
||||
h = next(next(halfedge(f, *graph), *graph), *graph);
|
||||
points[2] = QPointF(get(uv, h).first, -get(uv, h).second);
|
||||
painter->drawPolygon(points,3);
|
||||
}
|
||||
|
||||
pen.setColor(Qt::red);
|
||||
pen.setWidth(0);
|
||||
painter->setPen(pen);
|
||||
for(std::size_t i =0; i<polylines.size(); ++i)
|
||||
{
|
||||
std::vector<QPointF> points;
|
||||
points.reserve(polylines[i].size());
|
||||
for(std::size_t j =0; j<polylines[i].size(); ++j)
|
||||
{
|
||||
Point_2 transfo_point = transfo.transform(polylines[i][j]);
|
||||
points.push_back(QPointF(transfo_point.x(),
|
||||
-transfo_point.y()));
|
||||
}
|
||||
painter->drawPolyline(points.data(), static_cast<int>(points.size()));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QString texMesh_name;
|
||||
QRectF bounding_rect;
|
||||
Component* component;
|
||||
const std::vector<std::vector<EPICK::Point_2> >& polylines;
|
||||
|
||||
SMesh* graph;
|
||||
EPICK::Aff_transformation_2 transfo;
|
||||
};
|
||||
|
||||
class Navigation : public CGAL::Qt::GraphicsViewNavigation
|
||||
{
|
||||
public:
|
||||
Navigation()
|
||||
:CGAL::Qt::GraphicsViewNavigation(),
|
||||
prev_pos(QPoint(0,0))
|
||||
{ }
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *ev)
|
||||
{
|
||||
QGraphicsView* v = qobject_cast<QGraphicsView*>(obj);
|
||||
if(v == NULL) {
|
||||
QWidget* viewport = qobject_cast<QWidget*>(obj);
|
||||
if(viewport == NULL) {
|
||||
return false;
|
||||
}
|
||||
v = qobject_cast<QGraphicsView*>(viewport->parent());
|
||||
if(v == NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
switch(ev->type())
|
||||
{
|
||||
case QEvent::MouseMove: {
|
||||
QMouseEvent* me = static_cast<QMouseEvent*>(ev);
|
||||
if(is_dragging)
|
||||
{
|
||||
qreal dir[2] = {v->mapToScene(me->pos()).x() - prev_pos.x(),
|
||||
v->mapToScene(me->pos()).y() - prev_pos.y()};
|
||||
|
||||
v->translate(dir[0],dir[1]);
|
||||
v->update();
|
||||
}
|
||||
prev_pos = v->mapToScene(me->pos());
|
||||
break;
|
||||
}
|
||||
|
||||
case QEvent::MouseButtonPress: {
|
||||
is_dragging = true;
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseButtonRelease: {
|
||||
is_dragging = false;
|
||||
break;
|
||||
}
|
||||
case QEvent::Wheel: {
|
||||
QWheelEvent* event = static_cast<QWheelEvent*>(ev);
|
||||
QPointF old_pos = v->mapToScene(event->pos());
|
||||
if(event->delta() <0)
|
||||
v->scale(1.2, 1.2);
|
||||
else
|
||||
v->scale(0.8, 0.8);
|
||||
QPointF new_pos = v->mapToScene(event->pos());
|
||||
QPointF delta = new_pos - old_pos;
|
||||
v->translate(delta.x(), delta.y());
|
||||
v->update();
|
||||
break;
|
||||
}
|
||||
|
||||
case QEvent::MouseButtonDblClick: {
|
||||
v->fitInView(v->scene()->itemsBoundingRect(), Qt::KeepAspectRatio);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CGAL::Qt::GraphicsViewNavigation::eventFilter(obj, ev);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
bool is_dragging;
|
||||
QPointF prev_pos;
|
||||
};
|
||||
|
||||
|
||||
class EngraveWidget :
|
||||
public QDockWidget,
|
||||
public Ui::EngraveWidget
|
||||
{
|
||||
public:
|
||||
EngraveWidget(QString name, QWidget *parent)
|
||||
:QDockWidget(name,parent)
|
||||
{
|
||||
setupUi(this);
|
||||
}
|
||||
};
|
||||
|
||||
class Q_DECL_EXPORT Engrave_text_plugin :
|
||||
public QObject,
|
||||
public Polyhedron_demo_plugin_helper
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
||||
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
|
||||
|
||||
private:
|
||||
typedef CGAL::Surface_mesh_shortest_path_traits<EPICK, SMesh> SP_traits;
|
||||
typedef CGAL::Surface_mesh_shortest_path<SP_traits> Surface_mesh_shortest_path;
|
||||
typedef Surface_mesh_shortest_path::Face_location Face_location;
|
||||
typedef CGAL::AABB_face_graph_triangle_primitive<SMesh> Primitive;
|
||||
typedef CGAL::AABB_traits<EPICK, Primitive> Tree_traits;
|
||||
typedef CGAL::AABB_tree<Tree_traits> Tree;
|
||||
typedef EPICK::Point_3 Point_3;
|
||||
Messages_interface* messages;
|
||||
|
||||
public :
|
||||
|
||||
void init(QMainWindow*,
|
||||
CGAL::Three::Scene_interface*,
|
||||
Messages_interface* m) Q_DECL_OVERRIDE{
|
||||
//get refs
|
||||
this->scene = Three::scene();
|
||||
this->mw = Three::mainWindow();
|
||||
messages = m;
|
||||
|
||||
//action
|
||||
QAction* actionFitText= new QAction("Fit Text", mw);
|
||||
connect(actionFitText, SIGNAL(triggered()),
|
||||
this, SLOT(showWidget()));
|
||||
_actions << actionFitText;
|
||||
//widget
|
||||
dock_widget = new EngraveWidget("Engraving", mw);
|
||||
dock_widget->setVisible(false); // do not show at the beginning
|
||||
addDockWidget(dock_widget);
|
||||
connect(dock_widget->visualizeButton, &QPushButton::clicked,
|
||||
this, &Engrave_text_plugin::visualize);
|
||||
connect(dock_widget->engraveButton, &QPushButton::clicked,
|
||||
this, &Engrave_text_plugin::engrave);
|
||||
connect(dock_widget->text_meshButton, &QPushButton::clicked,
|
||||
this, &Engrave_text_plugin::generateTextItem);
|
||||
connect(dock_widget->letter_checkBox, &QCheckBox::toggled,
|
||||
this, &Engrave_text_plugin::generateTextItem);
|
||||
|
||||
//items
|
||||
visu_item = nullptr;
|
||||
sel_item = nullptr;
|
||||
textMesh = nullptr;
|
||||
sm = nullptr;
|
||||
|
||||
//transfo
|
||||
angle = 0.0;
|
||||
scalX=1.0;
|
||||
scalY=1.0;
|
||||
translation = EPICK::Vector_2(0,0);
|
||||
pointsize = 15;
|
||||
locked = false;
|
||||
connect(dock_widget->text_prec_slider, &QSlider::valueChanged,
|
||||
this, [this](){
|
||||
pointsize = dock_widget->text_prec_slider->value();
|
||||
scene->setSelectedItem(scene->item_id(sel_item));
|
||||
visualize();
|
||||
});
|
||||
connect(dock_widget->scalX_slider, &QSlider::valueChanged,
|
||||
this, [this](){
|
||||
scalX = dock_widget->scalX_slider->value()/1000.0;
|
||||
scene->setSelectedItem(scene->item_id(sel_item));
|
||||
visualize();
|
||||
});
|
||||
connect(dock_widget->scalY_slider, &QSlider::valueChanged,
|
||||
this, [this](){
|
||||
scalY = dock_widget->scalY_slider->value()/1000.0;
|
||||
scene->setSelectedItem(scene->item_id(sel_item));
|
||||
visualize();
|
||||
});
|
||||
|
||||
connect(dock_widget->bot_slider, &QSlider::valueChanged,
|
||||
this, [this](){
|
||||
if(textMesh)
|
||||
generateTextItem();
|
||||
});
|
||||
|
||||
connect(dock_widget->top_slider, &QSlider::valueChanged,
|
||||
this, [this](){
|
||||
if(textMesh)
|
||||
generateTextItem();
|
||||
});
|
||||
|
||||
connect(dock_widget->reset_button, &QPushButton::clicked,
|
||||
this, [this](){
|
||||
cleanup();
|
||||
});
|
||||
|
||||
connect(dock_widget->t_up_pushButton, &QPushButton::clicked,
|
||||
this, [this](){
|
||||
translation += EPICK::Vector_2(0,0.005);
|
||||
scene->setSelectedItem(scene->item_id(sel_item));
|
||||
visualize();
|
||||
});
|
||||
|
||||
connect(dock_widget->t_down_pushButton, &QPushButton::clicked,
|
||||
this, [this](){
|
||||
translation -= EPICK::Vector_2(0,0.005);
|
||||
scene->setSelectedItem(scene->item_id(sel_item));
|
||||
visualize();
|
||||
});
|
||||
|
||||
connect(dock_widget->t_right_pushButton, &QPushButton::clicked,
|
||||
this, [this](){
|
||||
translation += EPICK::Vector_2(0.005,0);
|
||||
scene->setSelectedItem(scene->item_id(sel_item));
|
||||
visualize();
|
||||
});
|
||||
|
||||
connect(dock_widget->t_left_pushButton, &QPushButton::clicked,
|
||||
this, [this](){
|
||||
translation -= EPICK::Vector_2(0.005,0);
|
||||
scene->setSelectedItem(scene->item_id(sel_item));
|
||||
visualize();
|
||||
});
|
||||
connect(dock_widget->rot_slider, &QSlider::valueChanged,
|
||||
this, [this](){
|
||||
if(!locked)
|
||||
{
|
||||
angle = dock_widget->rot_slider->value() * CGAL_PI/180.0;
|
||||
scene->setSelectedItem(scene->item_id(sel_item));
|
||||
visualize();
|
||||
}
|
||||
});
|
||||
graphics_scene = new QGraphicsScene(dock_widget);
|
||||
dock_widget->graphicsView->setScene(graphics_scene);
|
||||
dock_widget->graphicsView->setRenderHints(QPainter::Antialiasing);
|
||||
navigation = new Navigation();
|
||||
dock_widget->graphicsView->installEventFilter(navigation);
|
||||
dock_widget->graphicsView->viewport()->installEventFilter(navigation);
|
||||
}
|
||||
bool applicable(QAction*) const Q_DECL_OVERRIDE
|
||||
{
|
||||
return qobject_cast<Scene_polyhedron_selection_item*>
|
||||
(scene->item(scene->mainSelectionIndex()));
|
||||
}
|
||||
QList<QAction*> actions() const Q_DECL_OVERRIDE{
|
||||
return _actions;
|
||||
}
|
||||
public Q_SLOTS:
|
||||
void showWidget()
|
||||
{
|
||||
dock_widget->setVisible(!dock_widget->isVisible());
|
||||
}
|
||||
|
||||
void visualize() {
|
||||
if(!sel_item)
|
||||
sel_item =
|
||||
qobject_cast<Scene_polyhedron_selection_item*>
|
||||
(scene->item(scene->mainSelectionIndex()));
|
||||
if(!sel_item)
|
||||
return;
|
||||
if(sel_item->selected_facets.empty())
|
||||
{
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
if(!CGAL::is_closed(*sel_item->polyhedron()))
|
||||
{
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
if(visu_item)
|
||||
scene->erase(scene->item_id(visu_item));
|
||||
visu_item = nullptr;
|
||||
|
||||
if(!sm)
|
||||
{
|
||||
sm = new SMesh();
|
||||
sel_item->export_selected_facets_as_polyhedron(sm);
|
||||
SMesh::Halfedge_index hd =
|
||||
CGAL::Polygon_mesh_processing::longest_border(*sm).first;
|
||||
SMesh::Property_map<SMesh::Vertex_index, EPICK::Point_2> uv_map =
|
||||
sm->add_property_map<SMesh::Vertex_index, EPICK::Point_2>("v:uv").first;
|
||||
|
||||
// Parameterized bool pmap
|
||||
boost::unordered_set<SMesh::Vertex_index> vs;
|
||||
SMP::internal::Bool_property_map< boost::unordered_set<SMesh::Vertex_index> > vpm(vs);
|
||||
|
||||
// Parameterizer
|
||||
SMP::ARAP_parameterizer_3<SMesh> parameterizer;
|
||||
|
||||
SMP::Error_code status = parameterizer.parameterize(*sm, hd, uv_map,
|
||||
get(boost::vertex_index, *sm), vpm);
|
||||
if(status != SMP::OK) {
|
||||
std::cout << "Encountered a problem: " << status << std::endl;
|
||||
cleanup();
|
||||
return ;
|
||||
}
|
||||
|
||||
std::cout << "Parameterized with ARAP (SM) computed." << std::endl;
|
||||
xmin = std::numeric_limits<double>::max();
|
||||
xmax = std::numeric_limits<double>::min();
|
||||
ymin = std::numeric_limits<double>::max();
|
||||
ymax = std::numeric_limits<double>::min();
|
||||
uv_map_3 =
|
||||
sm->add_property_map<SMesh::Vertex_index, Point_3>("v:uv3").first;
|
||||
for(SMesh::Vertex_index v : sm->vertices())
|
||||
{
|
||||
uv_map_3[v] = Point_3(uv_map[v][0], uv_map[v]
|
||||
[1], 0);
|
||||
if(uv_map[v][0] > xmax)
|
||||
xmax = uv_map[v][0];
|
||||
if(uv_map[v][0] < xmin)
|
||||
xmin = uv_map[v][0];
|
||||
|
||||
if(uv_map[v][1] > ymax)
|
||||
ymax = uv_map[v][1];
|
||||
if(uv_map[v][1] < ymin)
|
||||
ymin = uv_map[v][1];
|
||||
}
|
||||
|
||||
CGAL::linear_least_squares_fitting_2(
|
||||
uv_map.begin(),
|
||||
uv_map.end(),
|
||||
bf_line,
|
||||
CGAL::Dimension_tag<0>());
|
||||
|
||||
EPICK::Vector_2 A(bf_line.to_vector()),
|
||||
B(EPICK::Point_2(0,0),
|
||||
EPICK::Point_2(1,0));
|
||||
if (A.x()<0) A=-A;
|
||||
angle = std::acos(A.x()/CGAL::sqrt(A.squared_length()));
|
||||
if ( A.y()<0 ) angle+=3*CGAL_PI/2.;
|
||||
if (angle>2*CGAL_PI) angle-=2*CGAL_PI;
|
||||
|
||||
locked = true;
|
||||
dock_widget->rot_slider->setSliderPosition(angle*180.0/CGAL_PI);
|
||||
locked = false;
|
||||
}
|
||||
//create Text Polyline
|
||||
QPainterPath path;
|
||||
QFont font;
|
||||
font.setPointSize(pointsize);
|
||||
path.addText(QPoint(xmin,ymin), font, dock_widget->lineEdit->text());
|
||||
QList<QPolygonF> polys = path.toSubpathPolygons();
|
||||
polylines.clear();
|
||||
float pxmin(8000),pxmax(-8000),
|
||||
pymin(8000), pymax(-8000);
|
||||
|
||||
Q_FOREACH(QPolygonF poly, polys){
|
||||
Q_FOREACH(QPointF pf, poly)
|
||||
{
|
||||
EPICK::Point_2 v = EPICK::Point_2(pf.x(),-pf.y());
|
||||
if(v.x() < pxmin)
|
||||
pxmin = v.x();
|
||||
if(v.x() > pxmax)
|
||||
pxmax = v.x();
|
||||
if(v.y() < pymin)
|
||||
pymin = v.y();
|
||||
if(v.y() > pymax)
|
||||
pymax = v.y();
|
||||
}
|
||||
}
|
||||
Q_FOREACH(QPolygonF poly, polys){
|
||||
polylines.push_back(std::vector<EPICK::Point_2>());
|
||||
Q_FOREACH(QPointF pf, poly)
|
||||
{
|
||||
EPICK::Point_2 v = EPICK::Point_2(pf.x(),-pf.y());
|
||||
polylines.back().push_back(EPICK::Point_2(v.x()*(xmax-xmin)/(pxmax-pxmin) +xmin ,
|
||||
v.y()*(ymax-ymin)/(pymax-pymin)+ymin
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// build AABB-tree for face location queries
|
||||
Tree aabb_tree(faces(*sm).first, faces(*sm).second, *sm, uv_map_3);
|
||||
|
||||
visu_item = new Scene_polylines_item;
|
||||
|
||||
|
||||
// compute 3D coordinates
|
||||
transfo =
|
||||
EPICK::Aff_transformation_2(CGAL::TRANSLATION,
|
||||
EPICK::Vector_2((xmax-xmin)/2+xmin,
|
||||
(ymax-ymin)/2+ymin)+ translation)
|
||||
* EPICK::Aff_transformation_2(CGAL::ROTATION,sin(angle), cos(angle))
|
||||
* EPICK::Aff_transformation_2(scalX, 0.0,0.0,scalY)
|
||||
* EPICK::Aff_transformation_2(CGAL::TRANSLATION,
|
||||
EPICK::Vector_2(-(xmax-xmin)/2-xmin,
|
||||
-(ymax-ymin)/2-ymin));
|
||||
BOOST_FOREACH(const std::vector<EPICK::Point_2>& polyline, polylines)
|
||||
{
|
||||
visu_item->polylines.push_back(std::vector<Point_3>());
|
||||
BOOST_FOREACH(const EPICK::Point_2& p, polyline)
|
||||
{
|
||||
EPICK::Point_2 p_2 = transfo.transform(p);
|
||||
|
||||
Face_location loc = Surface_mesh_shortest_path::locate(
|
||||
Point_3(p_2.x(), p_2.y(), 0),
|
||||
aabb_tree, *sm, uv_map_3);
|
||||
visu_item->polylines.back().push_back(
|
||||
Surface_mesh_shortest_path::point(loc.first, loc.second, *sm, sm->points()));
|
||||
}
|
||||
}
|
||||
visu_item->setName("Text");
|
||||
visu_item->setColor(QColor(Qt::red));
|
||||
scene->addItem(visu_item);
|
||||
dock_widget->engraveButton->setEnabled(true);
|
||||
dock_widget->text_meshButton->setEnabled(true);
|
||||
|
||||
if(graphics_scene->items().empty())
|
||||
{
|
||||
Component* component = new Component();
|
||||
face_iterator bfit;
|
||||
for(bfit = faces(*sm).begin();
|
||||
bfit != faces(*sm).end();
|
||||
++bfit)
|
||||
{
|
||||
component->insert(*bfit);
|
||||
}
|
||||
SMesh::Property_map<halfedge_descriptor,std::pair<float, float> > uv;
|
||||
uv = sm->add_property_map<halfedge_descriptor,std::pair<float, float> >(
|
||||
"h:uv",std::make_pair(0.0f,0.0f)).first;
|
||||
SMesh::Halfedge_iterator it;
|
||||
SMesh::Property_map<SMesh::Vertex_index, EPICK::Point_2> uv_map =
|
||||
sm->property_map<SMesh::Vertex_index, EPICK::Point_2>("v:uv").first;
|
||||
for(it = sm->halfedges_begin();
|
||||
it != sm->halfedges_end();
|
||||
++it)
|
||||
{
|
||||
halfedge_descriptor hd(*it);
|
||||
EPICK::FT u = uv_map[target(hd, *sm)].x();
|
||||
EPICK::FT v = uv_map[target(hd, *sm)].y();
|
||||
put(uv, *it, std::make_pair(static_cast<float>(u),static_cast<float>(v)));
|
||||
}
|
||||
|
||||
//ParamItem does not take ownership of text_mesh_bottom
|
||||
ParamItem *param_item= new ParamItem(component, polylines, transfo, sm,
|
||||
QRectF(QPointF(xmin, -ymax), QPointF(xmax, -ymin)));
|
||||
graphics_scene->addItem(param_item);
|
||||
dock_widget->graphicsView->fitInView(param_item->boundingRect(), Qt::KeepAspectRatio);
|
||||
}
|
||||
else
|
||||
{
|
||||
ParamItem* param_item = static_cast<ParamItem*>(graphics_scene->items().first());
|
||||
param_item->set_transfo(transfo);
|
||||
dock_widget->graphicsView->activateWindow();
|
||||
graphics_scene->update();
|
||||
}
|
||||
// dock_widget->visualizeButton->setEnabled(false);
|
||||
}
|
||||
|
||||
void create_text_mesh(SMesh& text_mesh)
|
||||
{
|
||||
if(!visu_item)
|
||||
return;
|
||||
if(!sel_item)
|
||||
return;
|
||||
if(sel_item->selected_facets.empty())
|
||||
return;
|
||||
if(!CGAL::is_closed(*sel_item->polyhedron()))
|
||||
return;
|
||||
CDT cdt;
|
||||
//polylines is duplicated so the transformation is only performed once
|
||||
std::vector<std::vector<EPICK::Point_2> > local_polylines
|
||||
= polylines;
|
||||
try{
|
||||
for(std::size_t i = 0;
|
||||
i < local_polylines.size(); ++i)
|
||||
{
|
||||
std::vector<Point_2>& points = local_polylines[i];
|
||||
for(std::size_t j = 0; j< points.size(); ++j)
|
||||
{
|
||||
Point_2 &p = points[j];
|
||||
p = transfo.transform(p);
|
||||
}
|
||||
cdt.insert_constraint(points.begin(),points.end());
|
||||
}
|
||||
}catch(std::runtime_error&)
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
throw;
|
||||
}
|
||||
if (cdt.dimension()!=2){
|
||||
QApplication::restoreOverrideCursor();
|
||||
std::cout << "Triangulation is not of dimension 2" << std::endl;
|
||||
return;
|
||||
}
|
||||
CGAL::Bbox_2 bbox= CGAL::bbox_2(local_polylines.front().begin(),
|
||||
local_polylines.front().end(),
|
||||
EPICK());
|
||||
Q_FOREACH(const std::vector<EPICK::Point_2>& points,
|
||||
local_polylines)
|
||||
{
|
||||
bbox += CGAL::bbox_2(points.begin(), points.end(), EPICK());
|
||||
}
|
||||
mark_nested_domains(cdt);
|
||||
|
||||
SMesh text_mesh_bottom;
|
||||
cdt2_to_face_graph(cdt,
|
||||
text_mesh_bottom);
|
||||
typedef boost::property_map<SMesh, CGAL::vertex_point_t>::type VPMap;
|
||||
typedef SMesh::Property_map<vertex_descriptor, EPICK::Vector_3> NPMAP;
|
||||
NPMAP vnormals =
|
||||
text_mesh_bottom.add_property_map<vertex_descriptor,
|
||||
EPICK::Vector_3 >("v:normal").first;
|
||||
|
||||
if(!dock_widget->letter_checkBox->isChecked())
|
||||
{
|
||||
CGAL::Polygon_mesh_processing::compute_vertex_normals(text_mesh_bottom, vnormals);
|
||||
}
|
||||
else{
|
||||
// \todo Computing normals before the final
|
||||
// mesh would be better.
|
||||
|
||||
//foreach CC
|
||||
SMesh::Property_map<face_descriptor, int> fcmap =
|
||||
text_mesh_bottom.add_property_map<face_descriptor, int>("f:cc", 0).first;
|
||||
std::size_t nb_cc = PMP::connected_components(text_mesh_bottom,
|
||||
fcmap);
|
||||
for(std::size_t cc = 0; cc<nb_cc; ++cc)
|
||||
{
|
||||
//compute the average normal for the cc give it to every vertex
|
||||
EPICK::Vector_3 normal(0,0,0);
|
||||
CGAL::Face_filtered_graph<SMesh> fmesh(text_mesh_bottom,
|
||||
static_cast<int>(cc),
|
||||
fcmap);
|
||||
BOOST_FOREACH(vertex_descriptor vd, vertices(fmesh))
|
||||
{
|
||||
normal += CGAL::Polygon_mesh_processing::compute_vertex_normal(vd, fmesh);
|
||||
}
|
||||
normal /= CGAL::sqrt(normal.squared_length());
|
||||
BOOST_FOREACH(vertex_descriptor vd, vertices(fmesh))
|
||||
{
|
||||
put(vnormals, vd, normal);
|
||||
}
|
||||
}
|
||||
}
|
||||
Bot<VPMap, NPMAP> bot(vnormals, dock_widget->bot_slider->value()/100000.0,
|
||||
get(CGAL::vertex_point, text_mesh));
|
||||
Top<VPMap, NPMAP> top(vnormals, get(CGAL::vertex_point, text_mesh),
|
||||
dock_widget->top_slider->value()/100000.0);
|
||||
PMP::extrude_mesh(text_mesh_bottom, text_mesh, bot, top);
|
||||
}
|
||||
|
||||
void engrave() {
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
SMesh text_mesh_complete;
|
||||
create_text_mesh(text_mesh_complete);
|
||||
|
||||
if (PMP::does_self_intersect(text_mesh_complete))
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
messages->information("Error: text mesh self-intersects!");
|
||||
return;
|
||||
}
|
||||
|
||||
SMesh result;
|
||||
CGAL::copy_face_graph(*sel_item->polyhedron(), result);
|
||||
bool OK = PMP::corefine_and_compute_difference(result, text_mesh_complete, result);
|
||||
|
||||
if (!OK)
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
messages->information("Error: the output mesh is not manifold!");
|
||||
return;
|
||||
}
|
||||
|
||||
CGAL::Polygon_mesh_processing::triangulate_faces(result);
|
||||
Scene_surface_mesh_item* result_item = new Scene_surface_mesh_item(
|
||||
result);
|
||||
scene->addItem(result_item);
|
||||
graphics_scene->clear();
|
||||
cleanup();
|
||||
if(textMesh)
|
||||
{
|
||||
textMesh->setVisible(false);
|
||||
}
|
||||
QApplication::restoreOverrideCursor();
|
||||
dock_widget->engraveButton->setEnabled(false);
|
||||
dock_widget->text_meshButton->setEnabled(false);
|
||||
dock_widget->visualizeButton->setEnabled(true);
|
||||
}
|
||||
|
||||
void generateTextItem()
|
||||
{
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
if(textMesh)
|
||||
{
|
||||
textMesh->face_graph()->clear();
|
||||
create_text_mesh(*textMesh->face_graph());
|
||||
textMesh->invalidateOpenGLBuffers();
|
||||
}
|
||||
else
|
||||
{
|
||||
SMesh text_mesh;
|
||||
create_text_mesh(text_mesh);
|
||||
textMesh = new Scene_surface_mesh_item(text_mesh);
|
||||
connect(textMesh, &Scene_surface_mesh_item::aboutToBeDestroyed,
|
||||
this, [this](){
|
||||
textMesh = nullptr;});
|
||||
textMesh->setName("Extruded Text");
|
||||
scene->addItem(textMesh);
|
||||
}
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
void closure()Q_DECL_OVERRIDE
|
||||
{
|
||||
dock_widget->hide();
|
||||
}
|
||||
|
||||
private:
|
||||
template <class CDT>
|
||||
void
|
||||
mark_domains(CDT& ct,
|
||||
typename CDT::Face_handle start,
|
||||
int index,
|
||||
std::list<typename CDT::Edge>& border )
|
||||
{
|
||||
if(start->info().nesting_level != -1){
|
||||
return;
|
||||
}
|
||||
std::list<typename CDT::Face_handle> queue;
|
||||
queue.push_back(start);
|
||||
while(! queue.empty()){
|
||||
typename CDT::Face_handle fh = queue.front();
|
||||
queue.pop_front();
|
||||
if(fh->info().nesting_level == -1){
|
||||
fh->info().nesting_level = index;
|
||||
for(int i = 0; i < 3; i++){
|
||||
typename CDT::Edge e(fh,i);
|
||||
typename CDT::Face_handle n = fh->neighbor(i);
|
||||
if(n->info().nesting_level == -1){
|
||||
if(ct.is_constrained(e)) border.push_back(e);
|
||||
else queue.push_back(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class CDT>
|
||||
void
|
||||
mark_nested_domains(CDT& cdt)
|
||||
{
|
||||
for(typename CDT::All_faces_iterator it = cdt.all_faces_begin(); it !=
|
||||
cdt.all_faces_end(); ++it){
|
||||
it->info().nesting_level = -1;
|
||||
}
|
||||
std::list<typename CDT::Edge> border;
|
||||
mark_domains(cdt, cdt.infinite_face(), 0, border);
|
||||
while(! border.empty()){
|
||||
typename CDT::Edge e = border.front();
|
||||
border.pop_front();
|
||||
typename CDT::Face_handle n = e.first->neighbor(e.second);
|
||||
if(n->info().nesting_level == -1){
|
||||
mark_domains(cdt, n, e.first->info().nesting_level+1, border);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class CDT, class TriangleMesh>
|
||||
void cdt2_to_face_graph(const CDT& cdt,
|
||||
TriangleMesh& tm)
|
||||
{
|
||||
|
||||
Tree aabb_tree(faces(*sm).first, faces(*sm).second, *sm, uv_map_3);
|
||||
typedef typename boost::graph_traits<TriangleMesh>::vertex_descriptor vertex_descriptor;
|
||||
|
||||
typedef std::map<typename CDT::Vertex_handle, vertex_descriptor> Map;
|
||||
Map descriptors;
|
||||
for (typename CDT::Finite_faces_iterator fit=cdt.finite_faces_begin(),
|
||||
fit_end=cdt.finite_faces_end();
|
||||
fit!=fit_end; ++fit)
|
||||
{
|
||||
if (!fit->info().in_domain()) continue;
|
||||
CGAL::cpp11::array<vertex_descriptor,3> vds;
|
||||
for(int i=0; i<3; ++i)
|
||||
{
|
||||
typename Map::iterator it;
|
||||
bool insert_ok;
|
||||
boost::tie(it,insert_ok) =
|
||||
descriptors.insert(std::make_pair(fit->vertex(i),vertex_descriptor()));
|
||||
if (insert_ok){
|
||||
const EPICK::Point_2& pt=fit->vertex(i)->point();
|
||||
Face_location loc = Surface_mesh_shortest_path::locate(
|
||||
Point_3(pt.x(), pt.y(), 0),
|
||||
aabb_tree, *sm, uv_map_3);
|
||||
it->second = add_vertex(Surface_mesh_shortest_path::point(loc.first, loc.second,
|
||||
*sm, sm->points()), tm);
|
||||
}
|
||||
vds[i]=it->second;
|
||||
}
|
||||
|
||||
CGAL::Euler::add_face(vds, tm);
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
dock_widget->scalX_slider->setValue(1000);
|
||||
dock_widget->scalY_slider->setValue(1000);
|
||||
dock_widget->rot_slider->setValue(0);
|
||||
translation = EPICK::Vector_2(0,0);
|
||||
uv_map_3.reset();
|
||||
graphics_scene->clear();
|
||||
if(sel_item)
|
||||
{
|
||||
scene->erase(scene->item_id(sel_item));
|
||||
sel_item =nullptr;
|
||||
}
|
||||
if(sm)
|
||||
{
|
||||
delete sm;
|
||||
sm = nullptr;
|
||||
}
|
||||
if(visu_item)
|
||||
{
|
||||
scene->erase(scene->item_id(visu_item));
|
||||
visu_item = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
QList<QAction*> _actions;
|
||||
EngraveWidget* dock_widget;
|
||||
Scene_polylines_item* visu_item;
|
||||
Scene_polyhedron_selection_item* sel_item;
|
||||
Scene_surface_mesh_item* textMesh;
|
||||
double angle;
|
||||
double scalX;
|
||||
double scalY;
|
||||
EPICK::Vector_2 translation;
|
||||
EPICK::Aff_transformation_2 transfo;
|
||||
std::vector<std::vector<EPICK::Point_2> > polylines;
|
||||
SMesh::Property_map<SMesh::Vertex_index, Point_3> uv_map_3;
|
||||
SMesh* sm;
|
||||
float xmin, xmax, ymin, ymax;
|
||||
int pointsize;
|
||||
bool locked;
|
||||
EPICK::Line_2 bf_line;
|
||||
QGraphicsScene *graphics_scene;
|
||||
Navigation* navigation;
|
||||
};
|
||||
#include "Engrave_text_plugin.moc"
|
||||
|
||||
Loading…
Reference in New Issue