@threepipe/plugin-svg-renderer
Version:
Plugins for SVG Rendering of 3d objects for Threepipe
193 lines (170 loc) • 4.76 kB
text/typescript
// Author: Axel Antoine
// mail: ax.antoine@gmail.com
// website: https://axantoine.com
// 17/03/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 {Vector3} from 'three';
import type {Face} from './Face';
import {Halfedge} from './Halfedge';
const _u = new Vector3();
let _idCount = 0;
export class Vertex {
/** Vertex position */
readonly position: Vector3 = new Vector3();
/** Reference to one halfedge starting from the vertex */
halfedge: Halfedge | null = null;
id: number;
constructor() {
this.id = _idCount;
_idCount++;
}
/**
* Returns a generator of free halfedges starting from this vertex.
* @param start The halfedge to start, default is vertex halfedge
*/
*freeHalfedgesOutLoop(start = this.halfedge) {
for (const halfedge of this.loopCW(start)) {
if (halfedge.isFree()) {
yield halfedge;
}
}
return null;
}
/**
* Returns a generator of free halfedges arriving to this vertex.
* @param start The halfedge to start, default is vertex halfedge
*/
*freeHalfedgesInLoop(start = this.halfedge) {
for (const halfedge of this.loopCW(start)) {
if (halfedge.twin.isFree()) {
yield halfedge.twin;
}
}
return null;
}
/**
* Returns a generator of boundary halfedges starting from this vertex.
* @param start The halfedge to start, default is vertex halfedge
*/
*boundaryHalfedgesOutLoop(start = this.halfedge) {
for (const halfedge of this.loopCW(start)) {
if (halfedge.isBoundary()) {
yield halfedge;
}
}
return null;
}
/**
* Returns a generator of boundary halfedges arriving to this vertex.
* @param start The halfedge to start, default is vertex halfedge
*/
*boundaryHalfedgesInLoop(start = this.halfedge) {
for (const halfedge of this.loopCW(start)) {
if (halfedge.twin.isBoundary()) {
yield halfedge.twin;
}
}
return null;
}
/**
* Returns whether the vertex is free, i.e. on of its ongoing halfedge has no
* face.
*
* @ref https://kaba.hilvi.org/homepage/blog/halfedge/halfedge.htm
*
* @returns `true` if free, `false` otherwise
*/
isFree() {
if (this.isIsolated()) {
return true;
}
for (const halfEdge of this.loopCW()) {
if (halfEdge.isFree()) {
return true;
}
}
return false;
}
isIsolated() {
return this.halfedge === null;
}
commonFacesWithVertex(other: Vertex) {
const faces = new Array<Face>();
for (const halfedge of this.loopCW()) {
if (halfedge.face && halfedge.face.hasVertex(other)) {
faces.push(halfedge.face);
}
}
return faces;
}
/**
* Checkes whether the vertex matches the given position
*
* @param {Vector3} position The position
* @param {number} [tolerance=1e-10] The tolerance
* @return {boolean}
*/
matchesPosition(position: Vector3, tolerance = 1e-10): boolean {
_u.subVectors(position, this.position);
return _u.length() < tolerance;
}
/**
* Returns the halfedge going from *this* vertex to *other* vertex if any.
* @param other The other vertex
* @returns `HalfEdge` if found, `null` otherwise.
*/
getHalfedgeToVertex(other: Vertex): Halfedge | null {
for (const halfEdge of this.loopCW()) {
if (halfEdge.twin.vertex === other) {
return halfEdge;
}
}
return null;
}
isConnectedToVertex(other: Vertex) {
return this.getHalfedgeToVertex(other) !== null;
}
static MAX_LOOP = Infinity;
/**
* Returns a generator of halfedges starting from this vertex in CW order.
* @param start The halfedge to start looping, default is vertex halfedge
*/
*loopCW(start = this.halfedge, maxLoop?: number) {
let i = 0
if (start && start.vertex === this) {
let curr: Halfedge = start;
do {
yield curr;
curr = curr.twin.next;
i++;
if(i>(maxLoop||Vertex.MAX_LOOP)){
break;
}
} while(curr != start);
}
return null;
}
/**
* Returns a generator of halfedges starting from this vertex in CCW order.
* @param start The halfedge to start, default is vertex halfedge
*/
*loopCCW(start = this.halfedge, maxLoop?: number) {
let i = 0
if (start && start.vertex === this) {
let curr: Halfedge = start;
do {
yield curr;
curr = curr.prev.twin;
i++;
if(i>(maxLoop||Vertex.MAX_LOOP)){
break;
}
} while(curr != start);
}
return null;
}
}