FreeCAD

Форк
0
/
TrimByPlane.cpp 
178 строк · 7.4 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2019 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24
#ifndef _PreComp_
25
#include <algorithm>
26
#endif
27

28
#include "Grid.h"
29
#include "Iterator.h"
30
#include "TrimByPlane.h"
31

32

33
using namespace MeshCore;
34

35
MeshTrimByPlane::MeshTrimByPlane(MeshKernel& rclM)
36
    : myMesh(rclM)
37
{}
38

39
void MeshTrimByPlane::CheckFacets(const MeshFacetGrid& rclGrid,
40
                                  const Base::Vector3f& base,
41
                                  const Base::Vector3f& normal,
42
                                  std::vector<FacetIndex>& trimFacets,
43
                                  std::vector<FacetIndex>& removeFacets) const
44
{
45
    // Go through the grid and check for each cell if its bounding box intersects the plane.
46
    // If the box is completely below the plane all facets will be kept, if it's above the
47
    // plane all triangles will be removed.
48
    std::vector<FacetIndex> checkElements;
49
    MeshGridIterator clGridIter(rclGrid);
50
    for (clGridIter.Init(); clGridIter.More(); clGridIter.Next()) {
51
        Base::BoundBox3f clBBox3d = clGridIter.GetBoundBox();
52
        if (clBBox3d.IsCutPlane(base, normal)) {
53
            // save all elements in checkElements
54
            clGridIter.GetElements(checkElements);
55
        }
56
        else if (clBBox3d.CalcPoint(Base::BoundBox3f::TLB).DistanceToPlane(base, normal) > 0.0f) {
57
            // save all elements in removeFacets
58
            clGridIter.GetElements(removeFacets);
59
        }
60
    }
61

62
    // remove double elements
63
    std::sort(checkElements.begin(), checkElements.end());
64
    checkElements.erase(std::unique(checkElements.begin(), checkElements.end()),
65
                        checkElements.end());
66

67
    trimFacets.reserve(checkElements.size() / 2);  // reserve some memory
68
    for (FacetIndex element : checkElements) {
69
        MeshGeomFacet clFacet = myMesh.GetFacet(element);
70
        if (clFacet.IntersectWithPlane(base, normal)) {
71
            trimFacets.push_back(element);
72
            removeFacets.push_back(element);
73
        }
74
        else if (clFacet._aclPoints[0].DistanceToPlane(base, normal) > 0.0f) {
75
            removeFacets.push_back(element);
76
        }
77
    }
78

79
    // remove double elements
80
    std::sort(removeFacets.begin(), removeFacets.end());
81
    removeFacets.erase(std::unique(removeFacets.begin(), removeFacets.end()), removeFacets.end());
82
}
83

84
void MeshTrimByPlane::CreateOneFacet(const Base::Vector3f& base,
85
                                     const Base::Vector3f& normal,
86
                                     unsigned short shift,
87
                                     const MeshGeomFacet& facet,
88
                                     std::vector<MeshGeomFacet>& trimmedFacets) const
89
{
90
    unsigned short nul = shift % 3;
91
    unsigned short one = (shift + 1) % 3;
92
    unsigned short two = (shift + 2) % 3;
93

94
    Base::Vector3f p1, p2;
95
    MeshGeomEdge edge;
96

97
    edge._aclPoints[0] = facet._aclPoints[nul];
98
    edge._aclPoints[1] = facet._aclPoints[one];
99
    edge.IntersectWithPlane(base, normal, p1);
100

101
    edge._aclPoints[0] = facet._aclPoints[nul];
102
    edge._aclPoints[1] = facet._aclPoints[two];
103
    edge.IntersectWithPlane(base, normal, p2);
104

105
    MeshGeomFacet create;
106
    create._aclPoints[0] = facet._aclPoints[nul];
107
    create._aclPoints[1] = p1;
108
    create._aclPoints[2] = p2;
109
    trimmedFacets.push_back(create);
110
}
111

112
void MeshTrimByPlane::CreateTwoFacet(const Base::Vector3f& base,
113
                                     const Base::Vector3f& normal,
114
                                     unsigned short shift,
115
                                     const MeshGeomFacet& facet,
116
                                     std::vector<MeshGeomFacet>& trimmedFacets) const
117
{
118
    unsigned short nul = shift % 3;
119
    unsigned short one = (shift + 1) % 3;
120
    unsigned short two = (shift + 2) % 3;
121

122
    Base::Vector3f p1, p2;
123
    MeshGeomEdge edge;
124

125
    edge._aclPoints[0] = facet._aclPoints[nul];
126
    edge._aclPoints[1] = facet._aclPoints[two];
127
    edge.IntersectWithPlane(base, normal, p1);
128

129
    edge._aclPoints[0] = facet._aclPoints[one];
130
    edge._aclPoints[1] = facet._aclPoints[two];
131
    edge.IntersectWithPlane(base, normal, p2);
132

133
    MeshGeomFacet create;
134
    create._aclPoints[0] = facet._aclPoints[nul];
135
    create._aclPoints[1] = facet._aclPoints[one];
136
    create._aclPoints[2] = p1;
137
    trimmedFacets.push_back(create);
138

139
    create._aclPoints[0] = facet._aclPoints[one];
140
    create._aclPoints[1] = p2;
141
    create._aclPoints[2] = p1;
142
    trimmedFacets.push_back(create);
143
}
144

145
void MeshTrimByPlane::TrimFacets(const std::vector<FacetIndex>& trimFacets,
146
                                 const Base::Vector3f& base,
147
                                 const Base::Vector3f& normal,
148
                                 std::vector<MeshGeomFacet>& trimmedFacets)
149
{
150
    trimmedFacets.reserve(2 * trimFacets.size());
151
    for (FacetIndex index : trimFacets) {
152
        MeshGeomFacet facet = myMesh.GetFacet(index);
153
        float dist1 = facet._aclPoints[0].DistanceToPlane(base, normal);
154
        float dist2 = facet._aclPoints[1].DistanceToPlane(base, normal);
155
        float dist3 = facet._aclPoints[2].DistanceToPlane(base, normal);
156

157
        // only one point below
158
        if (dist1 < 0.0f && dist2 > 0.0f && dist3 > 0.0f) {
159
            CreateOneFacet(base, normal, 0, facet, trimmedFacets);
160
        }
161
        else if (dist1 > 0.0f && dist2 < 0.0f && dist3 > 0.0f) {
162
            CreateOneFacet(base, normal, 1, facet, trimmedFacets);
163
        }
164
        else if (dist1 > 0.0f && dist2 > 0.0f && dist3 < 0.0f) {
165
            CreateOneFacet(base, normal, 2, facet, trimmedFacets);
166
        }
167
        // two points below
168
        else if (dist1 < 0.0f && dist2 < 0.0f && dist3 > 0.0f) {
169
            CreateTwoFacet(base, normal, 0, facet, trimmedFacets);
170
        }
171
        else if (dist1 > 0.0f && dist2 < 0.0f && dist3 < 0.0f) {
172
            CreateTwoFacet(base, normal, 1, facet, trimmedFacets);
173
        }
174
        else if (dist1 < 0.0f && dist2 > 0.0f && dist3 < 0.0f) {
175
            CreateTwoFacet(base, normal, 2, facet, trimmedFacets);
176
        }
177
    }
178
}
179

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.