add function to update texture of cut mesh
This commit is contained in:
@@ -357,6 +357,8 @@ SET(Mesh_SRCS
|
||||
MeshProperties.cpp
|
||||
MeshProperties.h
|
||||
MeshPyImp.cpp
|
||||
MeshTexture.cpp
|
||||
MeshTexture.h
|
||||
PreCompiled.cpp
|
||||
PreCompiled.h
|
||||
Segment.cpp
|
||||
|
||||
@@ -252,6 +252,30 @@ float MeshAlgorithm::GetAverageEdgeLength() const
|
||||
return fLen;
|
||||
}
|
||||
|
||||
float MeshAlgorithm::GetMinimumEdgeLength() const
|
||||
{
|
||||
float fLen = FLOAT_MAX;
|
||||
MeshFacetIterator cF(_rclMesh);
|
||||
for (cF.Init(); cF.More(); cF.Next()) {
|
||||
for (int i=0; i<3; i++)
|
||||
fLen = std::min(fLen, Base::Distance(cF->_aclPoints[i], cF->_aclPoints[(i+1)%3]));
|
||||
}
|
||||
|
||||
return fLen;
|
||||
}
|
||||
|
||||
float MeshAlgorithm::GetMaximumEdgeLength() const
|
||||
{
|
||||
float fLen = 0.0f;
|
||||
MeshFacetIterator cF(_rclMesh);
|
||||
for (cF.Init(); cF.More(); cF.Next()) {
|
||||
for (int i=0; i<3; i++)
|
||||
fLen = std::max(fLen, Base::Distance(cF->_aclPoints[i], cF->_aclPoints[(i+1)%3]));
|
||||
}
|
||||
|
||||
return fLen;
|
||||
}
|
||||
|
||||
Base::Vector3f MeshAlgorithm::GetGravityPoint() const
|
||||
{
|
||||
Base::Vector3f center;
|
||||
@@ -260,7 +284,7 @@ Base::Vector3f MeshAlgorithm::GetGravityPoint() const
|
||||
center += *cP;
|
||||
}
|
||||
|
||||
return center / (float)_rclMesh.CountPoints();
|
||||
return center / static_cast<float>(_rclMesh.CountPoints());
|
||||
}
|
||||
|
||||
void MeshAlgorithm::GetMeshBorders (std::list<std::vector<Base::Vector3f> > &rclBorders) const
|
||||
@@ -409,7 +433,7 @@ void MeshAlgorithm::GetFacetBorders (const std::vector<unsigned long> &raulInd,
|
||||
std::list<std::pair<unsigned long, unsigned long> > aclEdges;
|
||||
for (std::vector<unsigned long>::const_iterator it = raulInd.begin(); it != raulInd.end(); ++it) {
|
||||
const MeshFacet &rclFacet = rclFAry[*it];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (unsigned short i = 0; i < 3; i++) {
|
||||
unsigned long ulNB = rclFacet._aulNeighbours[i];
|
||||
if (ulNB != ULONG_MAX) {
|
||||
if (rclFAry[ulNB].IsFlag(MeshFacet::VISIT) == true)
|
||||
@@ -497,7 +521,7 @@ void MeshAlgorithm::GetMeshBorder(unsigned long uFacet, std::list<unsigned long>
|
||||
return;
|
||||
// add the open edge to the beginning of the list
|
||||
MeshFacetArray::_TConstIterator face = rFAry.begin() + uFacet;
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (unsigned short i = 0; i < 3; i++)
|
||||
{
|
||||
if (face->_aulNeighbours[i] == ULONG_MAX)
|
||||
openEdges.push_back(face->GetEdge(i));
|
||||
@@ -510,7 +534,7 @@ void MeshAlgorithm::GetMeshBorder(unsigned long uFacet, std::list<unsigned long>
|
||||
{
|
||||
if (it == face)
|
||||
continue;
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (unsigned short i = 0; i < 3; i++)
|
||||
{
|
||||
if (it->_aulNeighbours[i] == ULONG_MAX)
|
||||
openEdges.push_back(it->GetEdge(i));
|
||||
@@ -1036,7 +1060,7 @@ int MeshAlgorithm::Surround(const Base::BoundBox3f& rBox, const Base::Vector3f&
|
||||
|
||||
std::vector<MeshGeomFacet> cFacet(12);
|
||||
int id=0;
|
||||
for (int ii=0; ii<12; ii++) {
|
||||
for (size_t ii=0; ii<12; ii++) {
|
||||
cFacet[ii]._aclPoints[0]=cCorner[triangles[id++]];
|
||||
cFacet[ii]._aclPoints[1]=cCorner[triangles[id++]];
|
||||
cFacet[ii]._aclPoints[2]=cCorner[triangles[id++]];
|
||||
@@ -1679,10 +1703,10 @@ bool MeshAlgorithm::Distance (const Base::Vector3f &rclPt, unsigned long ulFacet
|
||||
float MeshAlgorithm::CalculateMinimumGridLength(float fLength, const Base::BoundBox3f& rBBox, unsigned long maxElements) const
|
||||
{
|
||||
// Max. limit of grid elements
|
||||
float fMaxGridElements=(float)maxElements;
|
||||
float fMaxGridElements=static_cast<float>(maxElements);
|
||||
|
||||
// estimate the minimum allowed grid length
|
||||
float fMinGridLen = (float)pow((rBBox.LengthX()*rBBox.LengthY()*rBBox.LengthZ()/fMaxGridElements), 0.3333f);
|
||||
float fMinGridLen = static_cast<float>(pow((rBBox.LengthX()*rBBox.LengthY()*rBBox.LengthZ()/fMaxGridElements), 0.3333f));
|
||||
return std::max<float>(fMinGridLen, fLength);
|
||||
}
|
||||
|
||||
@@ -1806,6 +1830,28 @@ MeshRefPointToFacets::operator[] (unsigned long pos) const
|
||||
return _map[pos];
|
||||
}
|
||||
|
||||
std::vector<unsigned long>
|
||||
MeshRefPointToFacets::GetIndices(unsigned long pos1, unsigned long pos2) const
|
||||
{
|
||||
std::vector<unsigned long> intersection;
|
||||
std::back_insert_iterator<std::vector<unsigned long> > result(intersection);
|
||||
const std::set<unsigned long>& set1 = _map[pos1];
|
||||
const std::set<unsigned long>& set2 = _map[pos2];
|
||||
std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), result);
|
||||
return intersection;
|
||||
}
|
||||
|
||||
std::vector<unsigned long>
|
||||
MeshRefPointToFacets::GetIndices(unsigned long pos1, unsigned long pos2, unsigned long pos3) const
|
||||
{
|
||||
std::vector<unsigned long> intersection;
|
||||
std::back_insert_iterator<std::vector<unsigned long> > result(intersection);
|
||||
std::vector<unsigned long> set1 = GetIndices(pos1, pos2);
|
||||
const std::set<unsigned long>& set2 = _map[pos3];
|
||||
std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), result);
|
||||
return intersection;
|
||||
}
|
||||
|
||||
void MeshRefPointToFacets::AddNeighbour(unsigned long pos, unsigned long facet)
|
||||
{
|
||||
_map[pos].insert(facet);
|
||||
@@ -1852,6 +1898,17 @@ MeshRefFacetToFacets::operator[] (unsigned long pos) const
|
||||
return _map[pos];
|
||||
}
|
||||
|
||||
std::vector<unsigned long>
|
||||
MeshRefFacetToFacets::GetIndices(unsigned long pos1, unsigned long pos2) const
|
||||
{
|
||||
std::vector<unsigned long> intersection;
|
||||
std::back_insert_iterator<std::vector<unsigned long> > result(intersection);
|
||||
const std::set<unsigned long>& set1 = _map[pos1];
|
||||
const std::set<unsigned long>& set2 = _map[pos2];
|
||||
std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), result);
|
||||
return intersection;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void MeshRefPointToPoints::Rebuild (void)
|
||||
|
||||
@@ -115,6 +115,14 @@ public:
|
||||
* Calculates the average length of edges.
|
||||
*/
|
||||
float GetAverageEdgeLength() const;
|
||||
/**
|
||||
* Calculates the minimum length of edges.
|
||||
*/
|
||||
float GetMinimumEdgeLength() const;
|
||||
/**
|
||||
* Calculates the maximum length of edges.
|
||||
*/
|
||||
float GetMaximumEdgeLength() const;
|
||||
/**
|
||||
* Calculates the gravity point of the mesh.
|
||||
*/
|
||||
@@ -373,6 +381,8 @@ public:
|
||||
/// Rebuilds up data structure
|
||||
void Rebuild (void);
|
||||
const std::set<unsigned long>& operator[] (unsigned long) const;
|
||||
std::vector<unsigned long> GetIndices(unsigned long, unsigned long) const;
|
||||
std::vector<unsigned long> GetIndices(unsigned long, unsigned long, unsigned long) const;
|
||||
MeshFacetArray::_TConstIterator GetFacet (unsigned long) const;
|
||||
std::set<unsigned long> NeighbourPoints(const std::vector<unsigned long>& , int level) const;
|
||||
std::set<unsigned long> NeighbourPoints(unsigned long) const;
|
||||
@@ -412,6 +422,8 @@ public:
|
||||
/// Returns a set of facets sharing one or more points with the facet with
|
||||
/// index \a ulFacetIndex.
|
||||
const std::set<unsigned long>& operator[] (unsigned long) const;
|
||||
/// Returns an array of common facets of the passed facet indexes.
|
||||
std::vector<unsigned long> GetIndices(unsigned long, unsigned long) const;
|
||||
|
||||
protected:
|
||||
const MeshKernel &_rclMesh; /**< The mesh kernel. */
|
||||
|
||||
106
src/Mod/Mesh/App/MeshTexture.cpp
Normal file
106
src/Mod/Mesh/App/MeshTexture.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2019 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* 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"
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
#include "MeshTexture.h"
|
||||
|
||||
using namespace Mesh;
|
||||
|
||||
MeshTexture::MeshTexture(const Mesh::MeshObject& mesh, const MeshCore::Material &material)
|
||||
: materialRefMesh(material)
|
||||
{
|
||||
countPointsRefMesh = mesh.countPoints();
|
||||
unsigned long countFacets = mesh.countFacets();
|
||||
|
||||
if (material.binding == MeshCore::MeshIO::PER_VERTEX && material.diffuseColor.size() == countPointsRefMesh) {
|
||||
binding = MeshCore::MeshIO::PER_VERTEX;
|
||||
kdTree.reset(new MeshCore::MeshKDTree(mesh.getKernel().GetPoints()));
|
||||
}
|
||||
else if (material.binding == MeshCore::MeshIO::PER_FACE && material.diffuseColor.size() == countFacets) {
|
||||
binding = MeshCore::MeshIO::PER_FACE;
|
||||
kdTree.reset(new MeshCore::MeshKDTree(mesh.getKernel().GetPoints()));
|
||||
refPnt2Fac.reset(new MeshCore::MeshRefPointToFacets(mesh.getKernel()));
|
||||
}
|
||||
}
|
||||
|
||||
void MeshTexture::apply(const Mesh::MeshObject& mesh, MeshCore::Material &material)
|
||||
{
|
||||
// copy the color values because the passed material could be the same instance as 'materialRefMesh'
|
||||
std::vector<App::Color> textureColor = materialRefMesh.diffuseColor;
|
||||
material.diffuseColor.clear();
|
||||
material.binding = MeshCore::MeshIO::OVERALL;
|
||||
|
||||
if (kdTree.get()) {
|
||||
// the points of the current mesh
|
||||
std::vector<App::Color> diffuseColor;
|
||||
const MeshCore::MeshPointArray& points = mesh.getKernel().GetPoints();
|
||||
const MeshCore::MeshFacetArray& facets = mesh.getKernel().GetFacets();
|
||||
|
||||
if (binding == MeshCore::MeshIO::PER_VERTEX) {
|
||||
diffuseColor.reserve(points.size());
|
||||
for (size_t index=0; index<points.size(); index++) {
|
||||
unsigned long pos = kdTree->FindExact(points[index]);
|
||||
if (pos < countPointsRefMesh) {
|
||||
diffuseColor.push_back(textureColor[pos]);
|
||||
}
|
||||
}
|
||||
|
||||
if (diffuseColor.size() == points.size()) {
|
||||
material.diffuseColor.swap(diffuseColor);
|
||||
material.binding = MeshCore::MeshIO::PER_VERTEX;
|
||||
}
|
||||
}
|
||||
else if (binding == MeshCore::MeshIO::PER_FACE) {
|
||||
// the values of the map give the point indices before the cut
|
||||
std::vector<unsigned long> pointMap;
|
||||
pointMap.reserve(points.size());
|
||||
for (size_t index=0; index<points.size(); index++) {
|
||||
unsigned long pos = kdTree->FindExact(points[index]);
|
||||
if (pos < countPointsRefMesh) {
|
||||
pointMap.push_back(pos);
|
||||
}
|
||||
}
|
||||
|
||||
// now determine the facet indices before the cut
|
||||
if (pointMap.size() == points.size()) {
|
||||
diffuseColor.reserve(facets.size());
|
||||
for (auto it : facets) {
|
||||
std::vector<unsigned long> found = refPnt2Fac->GetIndices(pointMap[it._aulPoints[0]],
|
||||
pointMap[it._aulPoints[1]],
|
||||
pointMap[it._aulPoints[2]]);
|
||||
if (found.size() == 1) {
|
||||
diffuseColor.push_back(textureColor[found.front()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (diffuseColor.size() == facets.size()) {
|
||||
material.diffuseColor.swap(diffuseColor);
|
||||
material.binding = MeshCore::MeshIO::PER_FACE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
66
src/Mod/Mesh/App/MeshTexture.h
Normal file
66
src/Mod/Mesh/App/MeshTexture.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2019 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* 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 *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef MESH_MESHTEXTURE_H
|
||||
#define MESH_MESHTEXTURE_H
|
||||
|
||||
#include <memory>
|
||||
#include "Core/Algorithm.h"
|
||||
#include "Core/MeshKernel.h"
|
||||
#include "Core/KDTree.h"
|
||||
#include "Mesh.h"
|
||||
|
||||
|
||||
namespace Mesh
|
||||
{
|
||||
|
||||
/*! The MeshTexture class.
|
||||
This algorithm is useful to update the material after a mesh has been modified
|
||||
by removing points or facets. It can't be used if the coordinates of points have
|
||||
changed or if new points have been added.
|
||||
@author Werner Mayer
|
||||
*/
|
||||
class MeshExport MeshTexture
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
A mesh with material. The number of points or facets must match with the number of colors.
|
||||
*/
|
||||
MeshTexture(const Mesh::MeshObject& mesh, const MeshCore::Material &material);
|
||||
/*!
|
||||
The \a mesh must be a sub-set of the mesh passed to the constructor. This means
|
||||
that points or facets can be removed but neither changed nor new points added.
|
||||
*/
|
||||
void apply(const Mesh::MeshObject& mesh, MeshCore::Material &material);
|
||||
|
||||
private:
|
||||
const MeshCore::Material &materialRefMesh;
|
||||
unsigned long countPointsRefMesh;
|
||||
std::unique_ptr<MeshCore::MeshKDTree> kdTree;
|
||||
std::unique_ptr<MeshCore::MeshRefPointToFacets> refPnt2Fac;
|
||||
MeshCore::MeshIO::Binding binding = MeshCore::MeshIO::OVERALL;
|
||||
};
|
||||
|
||||
} // namespace Mesh
|
||||
|
||||
#endif // MESH_MESHTEXTURE_H
|
||||
Reference in New Issue
Block a user