SmootherPlugin.cc 6.58 KB
Newer Older
Mike Kremer's avatar
Mike Kremer committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
//=============================================================================
//
//                               OpenFlipper
//        Copyright (C) 2008 by Computer Graphics Group, RWTH Aachen
//                           www.openflipper.org
//
//-----------------------------------------------------------------------------
//
//                                License
//
//  OpenFlipper is free software: 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.
//
//  OpenFlipper is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public License
//  along with OpenFlipper.  If not, see <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
Jan Möbius's avatar
Jan Möbius committed
25

Mike Kremer's avatar
Mike Kremer committed
26 27 28 29 30 31 32 33 34 35 36 37 38
//
//=============================================================================



#include "SmootherPlugin.hh"


#include <ObjectTypes/PolyMesh/PolyMesh.hh>
#include <ObjectTypes/TriangleMesh/TriangleMesh.hh>

#include "OpenFlipper/BasePlugin/PluginFunctions.hh"

Jan Möbius's avatar
Jan Möbius committed
39 40 41 42 43 44
SmootherPlugin::SmootherPlugin() :
        iterationsSpinbox_(0)
{

}

Jan Möbius's avatar
Jan Möbius committed
45
void SmootherPlugin::initializePlugin()
Mike Kremer's avatar
Mike Kremer committed
46 47 48 49
{
  // Create the Toolbox Widget
  QWidget* toolBox = new QWidget();

Jan Möbius's avatar
Jan Möbius committed
50
  QPushButton* smoothButton = new QPushButton("&Smooth", toolBox);
Mike Kremer's avatar
Mike Kremer committed
51

Jan Möbius's avatar
Jan Möbius committed
52
  iterationsSpinbox_ = new QSpinBox(toolBox);
Mike Kremer's avatar
Mike Kremer committed
53 54 55 56 57 58 59 60
  iterationsSpinbox_->setMinimum(1);
  iterationsSpinbox_->setMaximum(1000);
  iterationsSpinbox_->setSingleStep(1);

  QLabel* label = new QLabel("Iterations:");

  QGridLayout* layout = new QGridLayout(toolBox);

Jan Möbius's avatar
Jan Möbius committed
61 62 63
  layout->addWidget(label, 0, 0);
  layout->addWidget(smoothButton, 1, 1);
  layout->addWidget(iterationsSpinbox_, 0, 1);
Mike Kremer's avatar
Mike Kremer committed
64

Jan Möbius's avatar
Jan Möbius committed
65
  layout->addItem(new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding), 2, 0, 1, 2);
Mike Kremer's avatar
Mike Kremer committed
66

Jan Möbius's avatar
Jan Möbius committed
67
  connect(smoothButton, SIGNAL(clicked()), this, SLOT(simpleLaplace()));
Mike Kremer's avatar
Mike Kremer committed
68

Jan Möbius's avatar
Jan Möbius committed
69
  emit addToolbox(tr("Smoother"), toolBox);
Mike Kremer's avatar
Mike Kremer committed
70 71
}

72 73
/** \brief
 *
Mike Kremer's avatar
Mike Kremer committed
74
 */
Jan Möbius's avatar
Jan Möbius committed
75 76
void SmootherPlugin::simpleLaplace()
{
Mike Kremer's avatar
Mike Kremer committed
77

Jan Möbius's avatar
Jan Möbius committed
78 79
  for (PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS); o_it != PluginFunctions::objectsEnd();
      ++o_it) {
80

Jan Möbius's avatar
Jan Möbius committed
81
    if (o_it->dataType(DATA_TRIANGLE_MESH)) {
82

Mike Kremer's avatar
Mike Kremer committed
83 84
      // Get the mesh to work on
      TriMesh* mesh = PluginFunctions::triMesh(*o_it);
85

Mike Kremer's avatar
Mike Kremer committed
86
      // Property for the active mesh to store original point positions
Jan Möbius's avatar
Jan Möbius committed
87
      OpenMesh::VPropHandleT<TriMesh::Point> origPositions;
88

Mike Kremer's avatar
Mike Kremer committed
89
      // Add a property to the mesh to store original vertex positions
Jan Möbius's avatar
Jan Möbius committed
90
      mesh->add_property(origPositions, "SmootherPlugin_Original_Positions");
91

Jan Möbius's avatar
Jan Möbius committed
92
      for (int i = 0; i < iterationsSpinbox_->value(); ++i) {
93

Jan Möbius's avatar
Jan Möbius committed
94 95 96
        // Copy original positions to backup ( in vertex property )
        TriMesh::VertexIter v_it, v_end = mesh->vertices_end();
        for (v_it = mesh->vertices_begin(); v_it != v_end; ++v_it) {
97
          mesh->property(origPositions, *v_it) = mesh->point(*v_it);
Jan Möbius's avatar
Jan Möbius committed
98
        }
99

Jan Möbius's avatar
Jan Möbius committed
100 101
        // Do one smoothing step (For each point of the mesh ... )
        for (v_it = mesh->vertices_begin(); v_it != v_end; ++v_it) {
102

Jan Möbius's avatar
Jan Möbius committed
103
          TriMesh::Point point = TriMesh::Point(0.0, 0.0, 0.0);
104

Jan Möbius's avatar
Jan Möbius committed
105 106
          // Flag, to skip boundary vertices
          bool skip = false;
107

Jan Möbius's avatar
Jan Möbius committed
108
          // ( .. for each outgoing halfedge .. )
109
          TriMesh::VertexOHalfedgeIter voh_it(*mesh, *v_it);
Mike Kremer's avatar
Mike Kremer committed
110

111
          for (; voh_it.is_valid(); ++voh_it) {
Mike Kremer's avatar
Mike Kremer committed
112

Jan Möbius's avatar
Jan Möbius committed
113
            // .. add the (original) position of the neighbour ( end of the outgoing halfedge )
114
            point += mesh->property(origPositions, mesh->to_vertex_handle(*voh_it));
115

Jan Möbius's avatar
Jan Möbius committed
116 117
            // Check if the current Halfedge is a boundary halfedge
            // If it is, abort and keep the current vertex position
Jan Möbius's avatar
OM3  
Jan Möbius committed
118
            if (mesh->is_boundary(*voh_it)) {
Jan Möbius's avatar
Jan Möbius committed
119 120 121 122
              skip = true;
              break;
            }
          }
123

Jan Möbius's avatar
Jan Möbius committed
124
          // Devide by the valence of the current vertex
125
          point /= mesh->valence(*v_it);
126

Jan Möbius's avatar
Jan Möbius committed
127 128
          if (!skip) {
            // Set new position for the mesh if its not on the boundary
129
            mesh->point(*v_it) = point;
Jan Möbius's avatar
Jan Möbius committed
130 131
          }
        }
132

Jan Möbius's avatar
Jan Möbius committed
133
      }	    // Iterations end
134

Mike Kremer's avatar
Mike Kremer committed
135
      // Remove the property
Jan Möbius's avatar
Jan Möbius committed
136
      mesh->remove_property(origPositions);
137

Mike Kremer's avatar
Mike Kremer committed
138
      mesh->update_normals();
139

Jan Möbius's avatar
Jan Möbius committed
140
      emit updatedObject(o_it->id(),UPDATE_GEOMETRY);
Mike Kremer's avatar
Mike Kremer committed
141

Jan Möbius's avatar
Jan Möbius committed
142
    } else if (o_it->dataType(DATA_POLY_MESH)) {
Mike Kremer's avatar
Mike Kremer committed
143 144

      // Get the mesh to work on
145
      PolyMesh* mesh = PluginFunctions::polyMesh(*o_it);
Mike Kremer's avatar
Mike Kremer committed
146 147

      // Property for the active mesh to store original point positions
Jan Möbius's avatar
Jan Möbius committed
148
      OpenMesh::VPropHandleT<PolyMesh::Point> origPositions;
Mike Kremer's avatar
Mike Kremer committed
149 150

      // Add a property to the mesh to store original vertex positions
Jan Möbius's avatar
Jan Möbius committed
151
      mesh->add_property(origPositions, "SmootherPlugin_Original_Positions");
Mike Kremer's avatar
Mike Kremer committed
152

Jan Möbius's avatar
Jan Möbius committed
153
      for (int i = 0; i < iterationsSpinbox_->value(); ++i) {
Mike Kremer's avatar
Mike Kremer committed
154

Jan Möbius's avatar
Jan Möbius committed
155 156 157
        // Copy original positions to backup ( in Vertex property )
        PolyMesh::VertexIter v_it, v_end = mesh->vertices_end();
        for (v_it = mesh->vertices_begin(); v_it != v_end; ++v_it) {
158
          mesh->property(origPositions, *v_it) = mesh->point(*v_it);
Jan Möbius's avatar
Jan Möbius committed
159
        }
Mike Kremer's avatar
Mike Kremer committed
160

Jan Möbius's avatar
Jan Möbius committed
161 162
        // Do one smoothing step (For each point of the mesh ... )
        for (v_it = mesh->vertices_begin(); v_it != v_end; ++v_it) {
Mike Kremer's avatar
Mike Kremer committed
163

Jan Möbius's avatar
Jan Möbius committed
164
          PolyMesh::Point point = PolyMesh::Point(0.0, 0.0, 0.0);
Mike Kremer's avatar
Mike Kremer committed
165

Jan Möbius's avatar
Jan Möbius committed
166 167
          // Flag, to skip boundary vertices
          bool skip = false;
Mike Kremer's avatar
Mike Kremer committed
168

Jan Möbius's avatar
Jan Möbius committed
169
          // ( .. for each Outoing halfedge .. )
170 171
          PolyMesh::VertexOHalfedgeIter voh_it(*mesh, *v_it);
          for (; voh_it.is_valid(); ++voh_it) {
Jan Möbius's avatar
Jan Möbius committed
172
            // .. add the (original) position of the Neighbour ( end of the outgoing halfedge )
173
            point += mesh->property(origPositions, mesh->to_vertex_handle(*voh_it));
Mike Kremer's avatar
Mike Kremer committed
174

Jan Möbius's avatar
Jan Möbius committed
175 176
            // Check if the current Halfedge is a boundary halfedge
            // If it is, abort and keep the current vertex position
Jan Möbius's avatar
OM3  
Jan Möbius committed
177
            if (mesh->is_boundary(*voh_it)) {
Jan Möbius's avatar
Jan Möbius committed
178 179 180
              skip = true;
              break;
            }
Mike Kremer's avatar
Mike Kremer committed
181

Jan Möbius's avatar
Jan Möbius committed
182
          }
Mike Kremer's avatar
Mike Kremer committed
183

Jan Möbius's avatar
Jan Möbius committed
184
          // Devide by the valence of the current vertex
185
          point /= mesh->valence(*v_it);
Mike Kremer's avatar
Mike Kremer committed
186

Jan Möbius's avatar
Jan Möbius committed
187 188
          if (!skip) {
            // Set new position for the mesh if its not on the boundary
189
            mesh->point(*v_it) = point;
Jan Möbius's avatar
Jan Möbius committed
190 191
          }
        }
Mike Kremer's avatar
Mike Kremer committed
192

Jan Möbius's avatar
Jan Möbius committed
193
      }	    // Iterations end
Mike Kremer's avatar
Mike Kremer committed
194 195

      // Remove the property
Jan Möbius's avatar
Jan Möbius committed
196
      mesh->remove_property(origPositions);
Mike Kremer's avatar
Mike Kremer committed
197 198 199

      mesh->update_normals();

Jan Möbius's avatar
Jan Möbius committed
200
      emit updatedObject(o_it->id(),UPDATE_GEOMETRY);
Mike Kremer's avatar
Mike Kremer committed
201 202 203 204 205 206 207 208 209

    } else {

      emit log(LOGERR, "Data type not supported.");

    } // Switch data type
  }
}