Smoothing.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2009 Werner Mayer <wmayer[at]users.sourceforge.net>     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 #ifndef _PreComp_
00026 #endif
00027 
00028 #include "Smoothing.h"
00029 #include "MeshKernel.h"
00030 #include "Algorithm.h"
00031 #include "Elements.h"
00032 #include "Iterator.h"
00033 #include "Approximation.h"
00034 
00035 
00036 using namespace MeshCore;
00037 
00038 
00039 AbstractSmoothing::AbstractSmoothing(MeshKernel& m) : kernel(m)
00040 {
00041 }
00042 
00043 AbstractSmoothing::~AbstractSmoothing()
00044 {
00045 }
00046 
00047 void AbstractSmoothing::initialize(Component comp, Continuity cont)
00048 {
00049     this->component = comp;
00050     this->continuity = cont;
00051 }
00052 
00053 MeshSmoothing::MeshSmoothing(MeshKernel& m)
00054   : AbstractSmoothing(m)
00055 {
00056 }
00057 
00058 MeshSmoothing::~MeshSmoothing()
00059 {
00060 }
00061 
00062 void MeshSmoothing::Smooth(unsigned int iterations)
00063 {
00064     MeshCore::MeshPoint center;
00065     MeshCore::MeshPointArray PointArray = kernel.GetPoints();
00066 
00067     MeshCore::MeshPointIterator v_it(kernel);
00068     MeshCore::MeshRefPointToPoints vv_it(kernel);
00069     MeshCore::MeshPointArray::_TConstIterator v_beg = kernel.GetPoints().begin();
00070 
00071     for (unsigned int i=0; i<iterations; i++) {
00072         Base::Vector3f N, L;
00073         for (v_it.Begin(); v_it.More(); v_it.Next()) {
00074             MeshCore::PlaneFit pf;
00075             pf.AddPoint(*v_it);
00076             center = *v_it;
00077             const std::set<unsigned long>& cv = vv_it[v_it.Position()];
00078             if (cv.size() < 3)
00079                 continue;
00080 
00081             std::set<unsigned long>::const_iterator cv_it;
00082             for (cv_it = cv.begin(); cv_it !=cv.end(); ++cv_it) {
00083                 pf.AddPoint(v_beg[*cv_it]);
00084                 center += v_beg[*cv_it];
00085             }
00086 
00087             float scale = 1.0f/((float)cv.size()+1.0f);
00088             center.Scale(scale,scale,scale);
00089 
00090             // get the mean plane of the current vertex with the surrounding vertices
00091             pf.Fit();
00092             N = pf.GetNormal();
00093             N.Normalize();
00094 
00095             // look in which direction we should move the vertex
00096             L.Set(v_it->x - center.x, v_it->y - center.y, v_it->z - center.z);
00097             if (N*L < 0.0)
00098                 N.Scale(-1.0, -1.0, -1.0);
00099 
00100             // maximum value to move is distance to mean plane
00101             float d = std::min<float>((float)fabs(this->tolerance),(float)fabs(N*L));
00102             N.Scale(d,d,d);
00103 
00104             PointArray[v_it.Position()].Set(v_it->x - N.x, v_it->y - N.y, v_it->z - N.z);
00105         }
00106 
00107         // assign values without affecting iterators
00108         unsigned long count = kernel.CountPoints();
00109         for (unsigned long idx = 0; idx < count; idx++) {
00110             kernel.SetPoint(idx, PointArray[idx]);
00111         }
00112     }
00113 }
00114 
00115 LaplaceSmoothing::LaplaceSmoothing(MeshKernel& m)
00116   : AbstractSmoothing(m), lambda(0.6307)
00117 {
00118 }
00119 
00120 LaplaceSmoothing::~LaplaceSmoothing()
00121 {
00122 }
00123 
00124 void LaplaceSmoothing::Umbrella(const MeshRefPointToPoints& vv_it,
00125                                 const MeshRefPointToFacets& vf_it, double stepsize)
00126 {
00127     const MeshCore::MeshPointArray& points = kernel.GetPoints();
00128     MeshCore::MeshPointArray::_TConstIterator v_it,
00129     v_beg = points.begin(), v_end = points.end();
00130 
00131     unsigned long pos = 0;
00132     for (v_it = points.begin(); v_it != v_end; ++v_it,++pos) {
00133         const std::set<unsigned long>& cv = vv_it[pos];
00134         if (cv.size() < 3)
00135             continue;
00136         if (cv.size() != vf_it[pos].size()) {
00137             // do nothing for border points
00138             continue;
00139         }
00140 
00141         unsigned int n_count = cv.size();
00142         double w;
00143         w=1.0/double(n_count);
00144 
00145         double delx=0.0,dely=0.0,delz=0.0;
00146         std::set<unsigned long>::const_iterator cv_it;
00147         for (cv_it = cv.begin(); cv_it !=cv.end(); ++cv_it) {
00148             delx += w*((v_beg[*cv_it]).x-v_it->x);
00149             dely += w*((v_beg[*cv_it]).y-v_it->y);
00150             delz += w*((v_beg[*cv_it]).z-v_it->z);
00151         }
00152 
00153         float x = (float)(v_it->x+stepsize*delx);
00154         float y = (float)(v_it->y+stepsize*dely);
00155         float z = (float)(v_it->z+stepsize*delz);
00156         kernel.SetPoint(pos,x,y,z);
00157     }
00158 }
00159 
00160 void LaplaceSmoothing::Smooth(unsigned int iterations)
00161 {
00162     MeshCore::MeshRefPointToPoints vv_it(kernel);
00163     MeshCore::MeshRefPointToFacets vf_it(kernel);
00164 
00165     for (unsigned int i=0; i<iterations; i++) {
00166         Umbrella(vv_it, vf_it, lambda);
00167     }
00168 }
00169 
00170 TaubinSmoothing::TaubinSmoothing(MeshKernel& m)
00171   : LaplaceSmoothing(m), micro(0.0424)
00172 {
00173 }
00174 
00175 TaubinSmoothing::~TaubinSmoothing()
00176 {
00177 }
00178 
00179 void TaubinSmoothing::Smooth(unsigned int iterations)
00180 {
00181     MeshCore::MeshPointArray::_TConstIterator v_it;
00182     MeshCore::MeshRefPointToPoints vv_it(kernel);
00183     MeshCore::MeshRefPointToFacets vf_it(kernel);
00184 
00185     // Theoretically Taubin does not shrink the surface
00186     iterations = (iterations+1)/2; // two steps per iteration
00187     for (unsigned int i=0; i<iterations; i++) {
00188         Umbrella(vv_it, vf_it, lambda);
00189         Umbrella(vv_it, vf_it, -(lambda+micro));
00190     }
00191 }

Generated on Wed Nov 23 19:00:38 2011 for FreeCAD by  doxygen 1.6.1