Files
create/src/Mod/Cam/App/UniGridApprox.cpp

995 lines
27 KiB
C++

/***************************************************************************
* Copyright (c) 2007 *
* Joachim Zettler <Joachim.Zettler@gmx.de> *
* Human Rezai <Human@web.de> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#include "UniGridApprox.h"
#include "best_fit.h"
#include <Mod/Mesh/App/Core/Grid.h>
#include <Base/Builder3D.h>
#include <TColgp_Array2OfPnt.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <Geom_BSplineSurface.hxx>
#include <Handle_Geom_BSplineSurface.hxx>
//
///*********BINDINGS********/
#include <boost/numeric/bindings/traits/ublas_matrix.hpp>
#include <boost/numeric/bindings/atlas/cblas.hpp>
#include <boost/numeric/bindings/atlas/clapack.hpp>
//
using namespace boost::numeric::bindings;
typedef ublas::matrix<double, ublas::column_major> cm_t;
typedef ublas::symmetric_adaptor<cm_t, ublas::upper> adapt;
UniGridApprox::UniGridApprox(const MeshCore::MeshKernel &mesh, double Tol)
:m_Mesh(mesh),m_Tol(Tol),m_udeg(3),m_vdeg(3)
{
}
UniGridApprox::~UniGridApprox()
{
}
bool UniGridApprox::Perform(double TOL)
{
double maxErr;
cout << "MeshOffset" << endl;
MeshOffset();
cout << "SurfMeshParam" << endl;
SurfMeshParam();
while (true)
{
cout << "CompKnots" << endl;
CompKnots(uCP, vCP);
cout << "MatComp" << endl;
MatComp(uCP, vCP);
BuildSurf();
cout << "Compute Error";
maxErr = CompMeshError();
if (maxErr == -1)
throw Base::RuntimeError("CompError() couldn't project one point...");
cout << " -> " << maxErr << endl;
if (maxErr <= TOL) break;
else
{
if (uCP >= vCP)
{
uCP += 10;
vCP += vCP*10/uCP;
}
else
{
vCP += 10;
uCP += uCP*10/vCP;
}
}
if ( (uCP > (n_x + m_udeg + 1)) || (vCP > (n_y + m_vdeg + 1)) ) break;
m_Grid.clear();
m_Grid = m_GridCopy;
}
return true;
}
bool UniGridApprox::MeshOffset()
{
MeshCore::MeshPointIterator p_it(m_Mesh);
//vorläufige Lösung bis CAD-Normalen verwendet werden können
std::vector<Base::Vector3f> normals = best_fit::Comp_Normals(m_Mesh);
double x_max=-(1e+10),y_max=-(1e+10),z_max=-(1e+10),x_min=1e+10,y_min=1e+10,st_x,st_y;
int n = normals.size();
// führe verschiebung durch
//for(int i=0; i<n; ++i)
//{
// normals[i].Normalize();
// normals[i].Scale(m_offset,m_offset,m_offset);
// m_Mesh.MovePoint(i,normals[i]);
//}
// erzeuge nun ein uniformes Rechtecksgitter auf dem CAD-Netz
m_Mesh.RecalcBoundBox();
for (p_it.Begin(); p_it.More(); p_it.Next())
{
if (p_it->z>z_max) z_max = p_it->z;
if (p_it->x>x_max) x_max = p_it->x;
if (p_it->x<x_min) x_min = p_it->x;
if (p_it->y>y_max) y_max = p_it->y;
if (p_it->y<y_min) y_min = p_it->y;
}
// gittergrößen bestimmung über die bounding-box
n_x = int((x_max - x_min)/(y_max - y_min)*sqrt((x_max - x_min)*(y_max - y_min)));
n_y = int((y_max - y_min)/(x_max - x_min)*sqrt((x_max - x_min)*(y_max - y_min)));
st_x = (x_max - x_min)/n_x;
st_y = (y_max - y_min)/n_y;
uCP = n_x/10;
vCP = n_y/10;
m_Grid.resize(n_x+1);
for (int i=0; i<n_x+1; ++i)
m_Grid[i].resize(n_y+1);
unsigned long facetIndex;
MeshCore::MeshFacetGrid aFacetGrid(m_Mesh);
MeshCore::MeshAlgorithm malg(m_Mesh);
MeshCore::MeshAlgorithm malg2(m_Mesh);
Base::Vector3f projPoint, pnt, aNormal(0,0,1.0);
Base::Builder3D log3d;
pnt.z = float(z_max);
//gp_Pnt p;
//TColgp_Array2OfPnt Input(1,n_x+1,1,n_y+1);
for (int i=0; i<n_x+1; ++i)
{
cout << double(i)/double(n_x) << endl;
pnt.x = float(x_min + i*st_x);
for (int j=0; j<n_y+1 - 10; ++j)
{
pnt.y = float(y_min + j*st_y);
aNormal.z = 1.0;
if (!malg.NearestFacetOnRay(pnt, aNormal, aFacetGrid, projPoint, facetIndex))
{
aNormal.Scale(1,1,-1);// gridoptimiert
if (!malg.NearestFacetOnRay(pnt, aNormal, aFacetGrid, projPoint, facetIndex))
{
aNormal.Scale(1,1,-1);
if (!malg2.NearestFacetOnRay(pnt, aNormal, projPoint, facetIndex))
{
aNormal.Scale(1,1,-1);
if (!malg2.NearestFacetOnRay(pnt, aNormal, projPoint, facetIndex))
{
if (i != 0 && i !=n_x && j != 0 && j!= n_y)
{
pnt.x += float(st_x / 10.0);
aNormal.Scale(1,1,-1);
if (malg.NearestFacetOnRay(pnt, aNormal, aFacetGrid, projPoint, facetIndex))
{
log3d.addSinglePoint(projPoint, 3, 1,0,0);
m_Grid[i][j] = projPoint;
}
else
{
log3d.addSinglePoint(pnt, 3, 0,0,0);
pnt.z = 1e+10;
m_Grid[i][j] = pnt;
pnt.z = (float) z_max;
}
}
else
{
log3d.addSinglePoint(pnt, 3, 0,0,0);
m_Grid[i][j] = pnt;
}
}
else
{
log3d.addSinglePoint(projPoint, 3, 1,1,1);
m_Grid[i][j] = projPoint;
}
}
else
{
log3d.addSinglePoint(projPoint, 3, 1,1,1);
m_Grid[i][j] = projPoint;
}
}
else
{
log3d.addSinglePoint(projPoint, 3, 1,1,1);
m_Grid[i][j] = projPoint;
}
}
else
{
log3d.addSinglePoint(projPoint, 3, 1,1,1);
m_Grid[i][j] = projPoint;
}
}
}
int c=0;
for (int i=0; i<n_x+1; ++i)
{
for (int j=0; j<n_y+1; ++j)
{
c=0;
if (m_Grid[i][j].z == 1e+10)
{
m_Grid[i][j].x = 0;
m_Grid[i][j].y = 0;
m_Grid[i][j].z = 0;
if (m_Grid[i-1][j].z != 1e+10)
{
m_Grid[i][j] += (m_Grid[i-1][j]);
c++;
}
if (m_Grid[i][j-1].z != 1e+10)
{
m_Grid[i][j] += (m_Grid[i][j-1]);
c++;
}
if (m_Grid[i][j+1].z != 1e+10)
{
m_Grid[i][j] += (m_Grid[i][j+1]);
c++;
}
if (m_Grid[i+1][j].z != 1e+10)
{
m_Grid[i][j] += (m_Grid[i+1][j]);
c++;
}
m_Grid[i][j].Scale( float(1.0 / double(c)), float(1.0 / double(c)), float(1.0 / double(c)));;
log3d.addSinglePoint(m_Grid[i][j], 3, 0,0,0);
}
}
}
m_GridCopy = m_Grid;
log3d.saveToFile("c:/projection.iv");
return true;
}
bool UniGridApprox::SurfMeshParam()
{
// hier wird das in MeshOffset erzeugte gitter parametrisiert
// parametrisierung: (x,y) -> (u,v) , ( R x R ) -> ( [0,1] x [0,1] )
int n = m_Grid.size()-1; // anzahl der zu approximierenden punkte in x-richtung
int m = m_Grid[0].size()-1; // anzahl der zu approximierenden punkte in y-richtung
std::vector<double> dist_x, dist_y;
double sum,d;
Base::Vector3f vlen;
m_uParam.clear();
m_vParam.clear();
m_uParam.resize(n+1);
m_vParam.resize(m+1);
m_uParam[n] = 1.0;
m_vParam[m] = 1.0;
// berechne knotenvektor in u-richtung (entspricht x-richtung)
for (int j=0; j<m+1; ++j)
{
sum = 0.0;
dist_x.clear();
for (int i=0; i<n; ++i)
{
vlen = (m_Grid[i+1][j] - m_Grid[i][j]);
dist_x.push_back(vlen.Length());
sum += dist_x[i];
}
d = 0.0;
for (int i=0; i<n-1; ++i)
{
d += dist_x[i];
m_uParam[i+1] = m_uParam[i+1] + d/sum;
}
}
for (int i=0; i<n; ++i)
m_uParam[i] /= m+1;
// berechne knotenvektor in v-richtung (entspricht y-richtung)
for (int i=0; i<n+1; ++i)
{
sum = 0.0;
dist_y.clear();
for (int j=0; j<m; ++j)
{
vlen = (m_Grid[i][j+1] - m_Grid[i][j]);
dist_y.push_back(vlen.Length());
sum += dist_y[j];
}
d = 0.0;
for (int j=0; j<m-1; ++j)
{
d += dist_y[j];
m_vParam[j+1] = m_vParam[j+1] + d/sum;
}
}
for (int j=0; j<m; ++j)
m_vParam[j] /= n+1;
/*cout << "uParam:" << endl;
for(int i=0; i<m_uParam.size(); ++i){
cout << " " << m_uParam[i] << ", " << endl;
}
cout << "vParam:" << endl;
for(int i=0; i<m_vParam.size(); ++i){
cout << " " << m_vParam[i] << ", " << endl;
}*/
return true;
}
bool UniGridApprox::CompKnots(int u_CP, int v_CP)
{
// berechnung der knotenvektoren
// siehe NURBS-BOOK Seite 412
int r = n_x;
int s = n_y;
int n = u_CP-1;
int m = v_CP-1;
m_um = u_CP;
m_vm = v_CP;
int p = m_udeg;
int q = m_vdeg;
// U-Knot Vector Computation
double d = ((double)r + 1.0)/((double)n - (double)p + 1.0);
m_uknots.clear();
m_uknots.resize(n + p + 2);
for (int i=(p + 1) ; i<(n + p + 2); ++i)
m_uknots[i] = 1.0;
int ind;
double alp;
for (int i=1; i<(n - p + 1); ++i)
{
ind = int(i*d); // abgerundete ganze zahl
alp = i*d - ind; // rest
m_uknots[p+i] = ((1 - alp) * m_uParam[ind-1]) + (alp * m_uParam[ind]);
}
/*for(int i=0; i<m_uknots.size(); ++i){
cout << " " << m_uknots[i] << ", " << endl;
}*/
// V-Knot Vector Computation
d = ((double)s + 1.0)/((double)m - (double)q + 1.0);
m_vknots.clear();
m_vknots.resize(m + q + 2);
for (int i = (q + 1) ; i< (m + q + 2); ++i)
m_vknots[i] = 1.0;
for (int i=1; i<(m - q + 1); ++i)
{
ind = int(i*d); // abgerundete ganze zahl
alp = i*d - ind; // rest
m_vknots[q+i] = ((1 - alp) * m_vParam[ind-1]) + (alp * m_vParam[ind]);
}
/*for(int i=0; i<m_vknots.size(); ++i){
cout << " " << m_vknots[i] << ", " << endl;
}*/
return true;
}
bool UniGridApprox::MatComp(int u_CP, int v_CP)
{
// hier wird schließlich approximiert
int r = n_x;
int s = n_y;
int n = u_CP-1;
int m = v_CP-1;
int p = m_udeg;
int q = m_vdeg;
ublas::matrix<double> Nu_full(r - 1, n + 1);
ublas::matrix<double> Nv_full(s - 1, m + 1);
ublas::matrix<double> Nu_left(r - 1, n - 1);
ublas::matrix<double> Nv_left(s - 1, m - 1);
ublas::matrix<double> Nu (n - 1, n - 1);
ublas::matrix<double> Nv (m - 1, m - 1);
ublas::matrix<double> bx (1, n - 1);
ublas::matrix<double> by (1, n - 1);
ublas::matrix<double> bz (1, n - 1);
// mit null vorinitialisieren
for (int i=0; i<r-1; ++i)
for (int j=0; j<n+1; ++j)
Nu_full(i,j) = 0.0;
for (int i=0; i<s-1; ++i)
for (int j=0; j<m+1; ++j)
Nv_full(i,j) = 0.0;
std::vector<double> output(p+1);
int ind;
for (int i=1; i<r; ++i)
{
output.clear();
output.resize(p+1);
ind = Routines::FindSpan(n, p, m_uParam[i],m_uknots);
Routines::Basisfun(ind,m_uParam[i],p,m_uknots,output);
for (unsigned int j=0; j<output.size(); ++j)
{
Nu_full(i-1,ind-p+j) = output[j];
}
}
for (int i=0; i<r-1; ++i)
{
for (int j=0; j<n-1; ++j)
{
Nu_left(i,j) = Nu_full(i,j+1);
}
}
//WriteMatrix(Nu_full);
for (int i=1; i<s; ++i)
{
output.clear();
output.resize(q+1);
ind = Routines::FindSpan(m, q, m_vParam[i],m_vknots);
Routines::Basisfun(ind,m_vParam[i],q,m_vknots,output);
for (unsigned int j=0; j<output.size(); ++j)
{
Nv_full(i-1,ind-q+j) = output[j];
}
}
for (int i=0; i<s-1; ++i)
{
for (int j=0; j<m-1; ++j)
{
Nv_left(i,j) = Nv_full(i,j+1);
}
}
//cout << "NV" << endl;
//WriteMatrix(Nv_left);
atlas::gemm(CblasTrans,CblasNoTrans, 1.0, Nu_left,Nu_left, 0.0,Nu); // Nu_left'*Nu_left = Nu
atlas::gemm(CblasTrans,CblasNoTrans, 1.0, Nv_left,Nv_left, 0.0,Nv); // Nv_left'*Nv_left = Nv !!! Achtung !!!
std::vector<int> upiv(n - 1); // pivotelement
atlas::lu_factor(Nu,upiv); // führt LU-Zerlegung durch
std::vector<int> vpiv(m - 1);
atlas::lu_factor(Nv,vpiv);
ublas::matrix<double> uCP_x(n + 1, s + 1);
ublas::matrix<double> uCP_y(n + 1, s + 1);
ublas::matrix<double> uCP_z(n + 1, s + 1);
CPx.resize(n + 1, m + 1);
CPy.resize(n + 1, m + 1);
CPz.resize(n + 1, m + 1);
// mit null vorinitialisieren
for (int i=0; i<n+1; ++i)
for (int j=0; j<s+1; ++j)
{
uCP_x(i,j) = 0.0;
uCP_y(i,j) = 0.0;
uCP_z(i,j) = 0.0;
}
std::vector< ublas::matrix<double> > Ru_x(s+1);
std::vector< ublas::matrix<double> > Ru_y(s+1);
std::vector< ublas::matrix<double> > Ru_z(s+1);
for (int j=0; j<s+1; ++j)
{
Ru_x[j].resize(r-1,1);
Ru_y[j].resize(r-1,1);
Ru_z[j].resize(r-1,1);
uCP_x(0,j) = m_Grid[0][j].x;
uCP_y(0,j) = m_Grid[0][j].y;
uCP_z(0,j) = m_Grid[0][j].z;
uCP_x(n,j) = m_Grid[r][j].x;
uCP_y(n,j) = m_Grid[r][j].y;
uCP_z(n,j) = m_Grid[r][j].z;
for (int k=0; k<r-1; ++k)
{
Ru_x[j](k,0) = m_Grid[k+1][j].x - Nu_full(k,0)*m_Grid[0][j].x - Nu_full(k,n)*m_Grid[r][j].x;
Ru_y[j](k,0) = m_Grid[k+1][j].y - Nu_full(k,0)*m_Grid[0][j].y - Nu_full(k,n)*m_Grid[r][j].y;
Ru_z[j](k,0) = m_Grid[k+1][j].z - Nu_full(k,0)*m_Grid[0][j].z - Nu_full(k,n)*m_Grid[r][j].z;
}
atlas::gemm(CblasTrans,CblasNoTrans, 1.0, Ru_x[j],Nu_left, 0.0, bx);
atlas::gemm(CblasTrans,CblasNoTrans, 1.0, Ru_y[j],Nu_left, 0.0, by);
atlas::gemm(CblasTrans,CblasNoTrans, 1.0, Ru_z[j],Nu_left, 0.0, bz);
atlas::getrs(CblasTrans,Nu,upiv,bx);
atlas::getrs(CblasTrans,Nu,upiv,by);
atlas::getrs(CblasTrans,Nu,upiv,bz);
for (int i=1; i<n; ++i)
{
uCP_x(i,j) = bx(0,i-1);
uCP_y(i,j) = by(0,i-1);
uCP_z(i,j) = bz(0,i-1);
}
}
Base::Builder3D log3d;
Base::Vector3f pnt,pnt1;
for (int j=0; j<s; ++j)
{
for (int i=0; i<n; ++i)
{
pnt.x = (float) uCP_x(i,j);
pnt.y = (float) uCP_y(i,j);
pnt.z = (float) uCP_z(i,j);
pnt1.x = (float) uCP_x(i+1,j);
pnt1.y = (float) uCP_y(i+1,j);
pnt1.z = (float) uCP_z(i+1,j);
log3d.addSingleLine(pnt,pnt1, 1, 1,0,0);
}
}
log3d.saveToFile("c:/ControlPoints_u.iv");
//CPx = uCP_x;
//CPy = uCP_y;
//CPz = uCP_z;
//return true;
m_Grid.clear();
m_Grid.resize(n+1);
for (int i=0; i<n+1; ++i)
m_Grid[i].resize(s+1);
for (int i=0; i<n+1; ++i)
{
for (int j=0; j<s+1; ++j)
{
m_Grid[i][j].x = (float) uCP_x(i,j);
m_Grid[i][j].y = (float) uCP_y(i,j);
m_Grid[i][j].z = (float) uCP_z(i,j);
}
}
//SurfMeshParam();
// mit null vorinitialisieren
for (int i=0; i<n + 1; ++i)
{
for (int j=0; j<m + 1; ++j)
{
CPx(i,j) = 0.0;
CPy(i,j) = 0.0;
CPz(i,j) = 0.0;
}
}
std::vector< ublas::matrix<double> > Rv_x(n+1);
std::vector< ublas::matrix<double> > Rv_y(n+1);
std::vector< ublas::matrix<double> > Rv_z(n+1);
Base::Builder3D log,logo;
for (int j=0; j<n+1; ++j)
{
Rv_x[j].resize(s-1,1);
Rv_y[j].resize(s-1,1);
Rv_z[j].resize(s-1,1);
CPx(j,0) = uCP_x(j,0);
CPy(j,0) = uCP_y(j,0);
CPz(j,0) = uCP_z(j,0);
CPx(j,m) = uCP_x(j,s);
CPy(j,m) = uCP_y(j,s);
CPz(j,m) = uCP_z(j,s);
for (int k=0; k<s-1; ++k)
{
Rv_x[j](k,0) = uCP_x(j,k+1) - Nv_full(k,0)*uCP_x(j,0) - Nv_full(k,m)*uCP_x(j,s);
Rv_y[j](k,0) = uCP_y(j,k+1) - Nv_full(k,0)*uCP_y(j,0) - Nv_full(k,m)*uCP_y(j,s);
Rv_z[j](k,0) = uCP_z(j,k+1) - Nv_full(k,0)*uCP_z(j,0) - Nv_full(k,m)*uCP_z(j,s);
pnt.x = (float) uCP_x(j,k+1);
pnt.y = (float) uCP_y(j,k+1);
pnt.z = (float) uCP_z(j,k+1);
pnt1.x = (float) uCP_x(j,k+2);
pnt1.y = (float) uCP_y(j,k+2);
pnt1.z = (float) uCP_z(j,k+2);
log.addSingleLine(pnt,pnt1, 1, 0,0,0);
}
bx.clear();
by.clear();
bz.clear();
bx.resize(1, m - 1);
by.resize(1, m - 1);
bz.resize(1, m - 1);
atlas::gemm(CblasTrans,CblasNoTrans, 1.0, Rv_x[j],Nv_left, 0.0, bx);
atlas::gemm(CblasTrans,CblasNoTrans, 1.0, Rv_y[j],Nv_left, 0.0, by);
atlas::gemm(CblasTrans,CblasNoTrans, 1.0, Rv_z[j],Nv_left, 0.0, bz);
atlas::getrs(CblasTrans,Nv,vpiv,bx);
atlas::getrs(CblasTrans,Nv,vpiv,by);
atlas::getrs(CblasTrans,Nv,vpiv,bz);
for (int i=1; i<m; ++i)
{
CPx(j,i) = bx(0,i-1);
CPy(j,i) = by(0,i-1);
CPz(j,i) = bz(0,i-1);
pnt.x = (float) CPx(j,i);
pnt.y = (float) CPy(j,i);
pnt.z = (float) CPz(j,i);
logo.addSinglePoint(pnt,2,0,0,0);
}
}
logo.saveToFile("c:/contrPnts.iv");
ublas::matrix<double> Tmp = CPz;
//glättung des kontrollpunktnetzes
for (int i=1; i<n; ++i)
{
for (int j=1; j<m; ++j)
{
/*CPz(i,j) = ((Tmp(i-1,j-1) + Tmp(i-1,j) + Tmp(i-1,j+1)) +
(Tmp(i,j-1) + Tmp(i,j) + Tmp(i,j+1)) +
(Tmp(i+1,j-1) + Tmp(i+1,j) + Tmp(i+1,j+1)))/9;*/
CPz(i,j) = (Tmp(i-1,j) + Tmp(i,j-1) + Tmp(i,j) + Tmp(i,j+1) +Tmp(i+1,j))/5;
}
}
//for(int i=1; i<n; ++i){
// for(int j=1; j<m; ++j){
// /*CPz(i,j) = ((Tmp(i-1,j-1) + Tmp(i-1,j) + Tmp(i-1,j+1)) +
// (Tmp(i,j-1) + Tmp(i,j) + Tmp(i,j+1)) +
// (Tmp(i+1,j-1) + Tmp(i+1,j) + Tmp(i+1,j+1)))/9;*/
// CPz(i,j) = (Tmp(i-1,j) + Tmp(i,j-1) + Tmp(i,j) + Tmp(i,j+1) +Tmp(i+1,j))/5;
// }
//}
return true;
}
bool UniGridApprox::BuildSurf()
{
gp_Pnt pnt;
TColgp_Array2OfPnt Poles(1,m_um,1,m_vm);
for (int i=0; i<m_um; ++i)
{
for (int j=0; j<m_vm; ++j)
{
pnt.SetX(CPx(i,j));
pnt.SetY(CPy(i,j));
pnt.SetZ(CPz(i,j));
Poles.SetValue(i+1,j+1,pnt);
}
}
int c=1;
for (unsigned int i=0; i<m_uknots.size()-1; ++i)
{
if (m_uknots[i+1] != m_uknots[i])
{
++c;
}
}
TColStd_Array1OfReal UKnots(1,c);
TColStd_Array1OfInteger UMults(1,c);
c=1;
for (unsigned int i=0; i<m_vknots.size()-1; ++i)
{
if (m_vknots[i+1] != m_vknots[i])
{
++c;
}
}
TColStd_Array1OfReal VKnots(1,c);
TColStd_Array1OfInteger VMults(1,c);
int d=0;
c=1;
for (unsigned int i=0; i<m_uknots.size(); ++i)
{
if (m_uknots[i+1] != m_uknots[i])
{
UKnots.SetValue(d+1,m_uknots[i]);
UMults.SetValue(d+1,c);
++d;
c=1;
}
else
{
++c;
}
if (i==(m_uknots.size()-2))
{
UKnots.SetValue(d+1,m_uknots[i+1]);
UMults.SetValue(d+1,c);
break;
}
}
d=0;
c=1;
for (unsigned int i=0; i<m_vknots.size(); ++i)
{
if (m_vknots[i+1] != m_vknots[i])
{
VKnots.SetValue(d+1,m_vknots[i]);
VMults.SetValue(d+1,c);
++d;
c=1;
}
else
{
++c;
}
if (i==(m_vknots.size()-2))
{
VKnots.SetValue(d+1,m_vknots[i+1]);
VMults.SetValue(d+1,c);
break;
}
}
/*cout << "UKnots: " << endl;
for(int i=0; i<UKnots.Upper(); ++i)
cout << UKnots.Value(i+1) << ", ";
cout << endl;
cout << "UMults: " << endl;
for(int i=0; i<UMults.Upper(); ++i)
cout << UMults.Value(i+1) << ", ";
cout << endl;
cout << "VKnots: " << endl;
for(int i=0; i<VKnots.Upper(); ++i)
cout << VKnots.Value(i+1) << ", ";
cout << endl;
cout << "VMults: " << endl;
for(int i=0; i<VMults.Upper(); ++i)
cout << VMults.Value(i+1) << ", ";
cout << endl;*/
const Handle(Geom_BSplineSurface) surface = new Geom_BSplineSurface(
Poles, // const TColgp_Array2OfPnt & Poles,
UKnots, // const TColStd_Array1OfReal & UKnots,
VKnots, // const TColStd_Array1OfReal & VKnots,
UMults, // const TColStd_Array1OfInteger & UMults,
VMults, // const TColStd_Array1OfInteger & VMults,
3, // const Standard_Integer UDegree,
3 // const Standard_Integer VDegree,
// const Standard_Boolean UPeriodic = Standard_False,
// const Standard_Boolean VPeriodic = Standard_False*/
);
aAdaptorSurface.Load(surface);
return true;
}
double UniGridApprox::CompGridError()
{
GeomAPI_ProjectPointOnSurf proj;
MeshCore::MeshPointIterator pIt(m_Mesh);
gp_Pnt pnt;
double tmp = 0.0;
mG_err.clear();
mG_err.resize(m_Grid.size());
for (unsigned int i=0; i<m_Grid.size(); ++i)
mG_err[i].resize(m_Grid[i].size());
for (unsigned int i=0; i<m_Grid.size(); ++i)
{
for (unsigned int j=0; j<m_Grid[i].size(); ++j)
{
pnt.SetCoord(m_Grid[i][j].x, m_Grid[i][j].y, m_Grid[i][j].z);
proj.Init(pnt,aAdaptorSurface.BSpline(),0.1);
if (proj.IsDone() == false)
return -1.0;
mG_err[i][j] = proj.LowerDistance();
if (mG_err[i][j] > tmp)
tmp = mG_err[i][j];
}
}
return tmp;
}
bool UniGridApprox::WriteMatrix(ublas::matrix<double> M)
{
int row = M.size1();
int col = M.size2();
for (int i=0; i<row; ++i)
{
for (int j=0; j<col; ++j)
{
cout << M(i,j) << ", ";
}
cout << endl;
}
return true;
}
double UniGridApprox::CompMeshError()
{
Base::Builder3D log3d;
MeshCore::MeshKernel mesh;
BRepBuilderAPI_MakeFace Face(aAdaptorSurface.BSpline());
GeomAPI_ProjectPointOnSurf proj;
best_fit::Tesselate_Face(Face.Face(), mesh, float(0.1));
cout << mesh.CountPoints() << endl;
std::vector<Base::Vector3f> normals = best_fit::Comp_Normals(mesh);
double tmp = 0.0, sqrdis;
double errSum = 0.0;
int c=0;
m_err.clear();
m_err.resize(mesh.CountPoints(), 0.0);
MeshCore::MeshFacetGrid aFacetGrid(m_Mesh);
MeshCore::MeshAlgorithm malg(m_Mesh);
MeshCore::MeshAlgorithm malg2(m_Mesh);
MeshCore::MeshPointIterator p_it(mesh);
Base::Vector3f projPoint, distVec, pnt;
unsigned long facetIndex;
for (p_it.Begin(); p_it.More(); p_it.Next())
{
if (!malg.NearestFacetOnRay(*p_it, normals[p_it.Position()], aFacetGrid, projPoint, facetIndex)) // gridoptimiert
{
if (malg2.NearestFacetOnRay(*p_it, normals[p_it.Position()], projPoint, facetIndex))
{
pnt.x = p_it->x;
pnt.y = p_it->y;
pnt.z = p_it->z;
log3d.addSingleLine(pnt,projPoint);
distVec = projPoint - pnt;
sqrdis = distVec*distVec;
}
else
{
cout << "oops, ";
continue;
}
}
else
{
pnt.x = p_it->x;
pnt.y = p_it->y;
pnt.z = p_it->z;
log3d.addSingleLine(pnt,projPoint);
distVec = projPoint - pnt;
sqrdis = distVec*distVec;
}
errSum += sqrt(sqrdis);
++c;
if (sqrt(sqrdis) > tmp)
{
m_err[p_it.Position()] = sqrt(sqrdis);
tmp = m_err[p_it.Position()];
}
}
log3d.saveToFile("c:/Error.iv");
return errSum/c;
}