add function to update texture of cut mesh

This commit is contained in:
wmayer
2019-09-18 23:25:45 +02:00
parent e60a561a9e
commit 54df95baa4
5 changed files with 250 additions and 7 deletions

View File

@@ -357,6 +357,8 @@ SET(Mesh_SRCS
MeshProperties.cpp
MeshProperties.h
MeshPyImp.cpp
MeshTexture.cpp
MeshTexture.h
PreCompiled.cpp
PreCompiled.h
Segment.cpp

View File

@@ -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)

View File

@@ -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. */

View 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;
}
}
}
}

View 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