-
Notifications
You must be signed in to change notification settings - Fork 2
/
HalfedgeDS.ts
191 lines (163 loc) · 5.33 KB
/
HalfedgeDS.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// Author: Axel Antoine
// mail: ax.antoine@gmail.com
// website: https://axantoine.com
// 23/02/2021
// Loki, Inria project-team with Université de Lille
// within the Joint Research Unit UMR 9189 CNRS-Centrale
// Lille-Université de Lille, CRIStAL.
// https://loki.lille.inria.fr
// LICENCE: Licence.md
import { BufferGeometry, Vector3 } from 'three';
import { Face } from './Face';
import { Vertex } from './Vertex';
import { Halfedge } from './Halfedge';
import { addEdge } from '../operations/addEdge';
import { addFace } from '../operations/addFace';
import { addVertex } from '../operations/addVertex';
import { removeVertex } from '../operations/removeVertex';
import { removeEdge } from '../operations/removeEdge';
import { removeFace } from '../operations/removeFace';
import { cutFace } from '../operations/cutFace';
import { splitEdge } from '../operations/splitEdge';
import { setFromGeometry } from '../operations/setFromGeometry';
/**
* Class representing an Halfedge Data Structure
*/
export class HalfedgeDS {
/** @readonly Faces */
readonly faces = new Array<Face>();
/** @readonly Vertices */
readonly vertices = new Array<Vertex>();
/** @readonly Halfedges */
readonly halfedges = new Array<Halfedge>();
/**
* Sets the halfedge structure from a BufferGeometry.
* @param geometry BufferGeometry to read
* @param tolerance Tolerance distance from which positions are considered equal
*/
setFromGeometry(geometry: BufferGeometry, tolerance = 1e-10) {
return setFromGeometry(this, geometry, tolerance);
}
/**
* Returns an array of all the halfedge loops in the structure.
*
* *Note: Actually returns an array of halfedges from which loop generator
* can be called*
*
* @returns
*/
loops() {
const loops = new Array<Halfedge>();
const handled = new Set<Halfedge>();
for (const halfedge of this.halfedges) {
if (!handled.has(halfedge)) {
for (const he of halfedge.nextLoop()) {
handled.add(he);
}
loops.push(halfedge);
}
}
return loops;
}
/**
* Clear the structure data
*/
clear() {
this.faces.clear();
this.vertices.clear();
this.halfedges.clear();
}
/**
* Adds a new vertex to the structure at the given position and returns it.
* If checkDuplicates is true, returns any existing vertex that matches the
* given position.
*
* @param position New vertex position
* @param checkDuplicates Enable/disable existing vertex matching, default false
* @param tolerance Tolerance used for vertices position comparison
* @returns
*/
addVertex(
position: Vector3,
checkDuplicates = false,
tolerance = 1e-10) {
return addVertex(this, position, checkDuplicates, tolerance);
}
/**
* Adds an edge (i.e. a pair of halfedges) between the given vertices.
* Requires vertices to be free, i.e., there is at least one free halfedge
* (i.e. without face) in their neighborhood.
*
* @param v1 First vertex to link
* @param v2 Second vertex to link
* @param allowParallels Allows multiple pair of halfedges between vertices, default false
* @returns Existing or new halfedge
*/
addEdge(v1: Vertex, v2: Vertex, allowParallels = false) {
return addEdge(this, v1, v2, allowParallels)
}
/**
* Adds a face to an existing halfedge loop
* @param halfedge
* @returns
*/
addFace(halfedges: Halfedge[]) {
return addFace(this, halfedges);
}
/**
* Removes a vertex from the structure
* @param vertex Vertex to remove
* @param mergeFaces If true, merges connected faces if any, otherwise removes them. Default true
*/
removeVertex(vertex: Vertex, mergeFaces = true) {
return removeVertex(this, vertex, mergeFaces);
}
/**
* Removes an edge from the structrure
* @param halfedge Halfedge to remove
* @param mergeFaces If true, merges connected faces if any, otherwise removes them. Default true
*/
removeEdge(halfedge: Halfedge, mergeFaces = true) {
return removeEdge(this, halfedge, mergeFaces);
}
/**
* Removes a face from the structure.
* @param face Face to remove
*/
removeFace(face: Face) {
return removeFace(this, face);
}
/**ts
* Cuts the `face` between the vertices `v1` and `v2`.
* v1 and v2 must either be vertices of the face or isolated vertices.
*
* To test if a new face is created, simply do
* ```
* const halfedge = struct.cutFace(face, v1, v2, true);
* if (halfedge.face !== halfedge.twin.face) {
* // Halfedge are on different faces / loops
* const existingFace = halfedge.face;
* const newFace = halfedge.twin.face;
* }
* ```
*
*
* @param face Face to cut
* @param v1 1st vertex
* @param v2 2nd vertex
* @param createNewFace wether to create a new face or not when cutting
* @returns the cutting halfedge
*/
cutFace(face: Face, v1: Vertex, v2: Vertex, createNewFace = true) {
return cutFace(this, face, v1, v2, createNewFace);
}
/**
* Splits the halfedge at position and returns the new vertex
* @param halfEdge The HalfEdge to be splitted
* @param position Position of the split vertex
* @returns the new created vertex
*/
splitEdge(halfedge: Halfedge, position: Vector3, tolerance = 1e-10) {
return splitEdge(this, halfedge, position, tolerance);
}
}