mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-06 16:33:15 +01:00
prefer-const rule for JS / auto fixes
This commit is contained in:
parent
0956f0647a
commit
f2369a5689
173 changed files with 1479 additions and 1476 deletions
|
|
@ -64,7 +64,10 @@
|
||||||
"max-len": "off",
|
"max-len": "off",
|
||||||
"no-console": "off",
|
"no-console": "off",
|
||||||
"no-extra-boolean-cast": "off",
|
"no-extra-boolean-cast": "off",
|
||||||
"no-var": "error"
|
"no-var": "error",
|
||||||
|
"prefer-const": ["error", {
|
||||||
|
"destructuring": "all"
|
||||||
|
}]
|
||||||
},
|
},
|
||||||
"ignorePatterns": [
|
"ignorePatterns": [
|
||||||
"/modules/math/optim/*.js",
|
"/modules/math/optim/*.js",
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,12 @@ export function box(w, h, d, tr) {
|
||||||
|
|
||||||
export function cylinder(r, h, tr) {
|
export function cylinder(r, h, tr) {
|
||||||
tr = tr || IDENTITY;
|
tr = tr || IDENTITY;
|
||||||
let normal = tr.apply(AXIS.Z);
|
const normal = tr.apply(AXIS.Z);
|
||||||
let plane = new Plane(normal, h);
|
const plane = new Plane(normal, h);
|
||||||
let csys = CSys.fromNormalAndDir(normal.multiply(h), normal, plane.basis()[0]);
|
const csys = CSys.fromNormalAndDir(normal.multiply(h), normal, plane.basis()[0]);
|
||||||
|
|
||||||
let circle1 = new Circle(-1, new Point(0,0,0), r).toNurbs(csys);
|
const circle1 = new Circle(-1, new Point(0,0,0), r).toNurbs(csys);
|
||||||
let circle2 = circle1.translate(tr.apply(new Point(0,0,-h)));
|
const circle2 = circle1.translate(tr.apply(new Point(0,0,-h)));
|
||||||
return enclose([circle1], [circle2]);
|
return enclose([circle1], [circle2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ export class BREPValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
validateShell(shell) {
|
validateShell(shell) {
|
||||||
for (let face of shell.faces) {
|
for (const face of shell.faces) {
|
||||||
if (face.shell !== shell) {
|
if (face.shell !== shell) {
|
||||||
this.addError('FACE_REFERS_TO_WRONG_SHELL', "face refers to a shell it doesn't belong to", {face, shell});
|
this.addError('FACE_REFERS_TO_WRONG_SHELL', "face refers to a shell it doesn't belong to", {face, shell});
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@ export class BREPValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
validateFace(face) {
|
validateFace(face) {
|
||||||
for (let loop of [face.outerLoop, ...face.innerLoops]) {
|
for (const loop of [face.outerLoop, ...face.innerLoops]) {
|
||||||
if (face !== loop.face) {
|
if (face !== loop.face) {
|
||||||
this.addError('LOOP_REFERS_TO_WRONG_FACE', 'loop refers to different face it belongs to', {loop, face});
|
this.addError('LOOP_REFERS_TO_WRONG_FACE', 'loop refers to different face it belongs to', {loop, face});
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +72,7 @@ BREPValidator.validateToConsole = function(shell) {
|
||||||
const brepValidator = new BREPValidator();
|
const brepValidator = new BREPValidator();
|
||||||
|
|
||||||
brepValidator.validateShell(shell);
|
brepValidator.validateShell(shell);
|
||||||
for (let brepError of brepValidator.errors) {
|
for (const brepError of brepValidator.errors) {
|
||||||
console.warn(brepError.message);
|
console.warn(brepError.message);
|
||||||
}
|
}
|
||||||
if (brepValidator.errors.length === 0) {
|
if (brepValidator.errors.length === 0) {
|
||||||
|
|
@ -81,7 +81,7 @@ BREPValidator.validateToConsole = function(shell) {
|
||||||
};
|
};
|
||||||
|
|
||||||
BREPValidator.validate = function(shell) {
|
BREPValidator.validate = function(shell) {
|
||||||
let validator = new BREPValidator();
|
const validator = new BREPValidator();
|
||||||
validator.validateShell(shell);
|
validator.validateShell(shell);
|
||||||
return validator.errors;
|
return validator.errors;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ class BRepDebug {
|
||||||
}
|
}
|
||||||
|
|
||||||
booleanLoopDetectionSuccess(loop) {
|
booleanLoopDetectionSuccess(loop) {
|
||||||
let ld = last(this.currentBooleanSession.loopDetection);
|
const ld = last(this.currentBooleanSession.loopDetection);
|
||||||
ld.detectedLoops.push(loop);
|
ld.detectedLoops.push(loop);
|
||||||
ld.steps.push({type: 'LOOP_FOUND'});
|
ld.steps.push({type: 'LOOP_FOUND'});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@ import {FaceIntersectionsExplorer} from "./faceIntersectionsExplorer";
|
||||||
export default class BrepDebugger extends React.PureComponent {
|
export default class BrepDebugger extends React.PureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {booleanSessions} = BREP_DEBUG;
|
const {booleanSessions} = BREP_DEBUG;
|
||||||
let {brepDebugGroup} = this.props;
|
const {brepDebugGroup} = this.props;
|
||||||
function hideAll() {
|
function hideAll() {
|
||||||
for (let obj of brepDebugGroup.children) {
|
for (const obj of brepDebugGroup.children) {
|
||||||
obj.visible = false;
|
obj.visible = false;
|
||||||
}
|
}
|
||||||
__DEBUG__.render();
|
__DEBUG__.render();
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,11 @@ import {
|
||||||
|
|
||||||
|
|
||||||
export function EdgeTransferExplorer({edge, face, chosenEdge, index, group3d}) {
|
export function EdgeTransferExplorer({edge, face, chosenEdge, index, group3d}) {
|
||||||
let category='edge-transfer';
|
const category='edge-transfer';
|
||||||
|
|
||||||
let chosenFace = chosenEdge ? chosenEdge.loop.face : null;
|
const chosenFace = chosenEdge ? chosenEdge.loop.face : null;
|
||||||
let discardedFace = chosenEdge ? chosenEdge.twin().loop.face : null;
|
const discardedFace = chosenEdge ? chosenEdge.twin().loop.face : null;
|
||||||
let context = {edge, face, chosenEdge, chosenFace, discardedFace};
|
const context = {edge, face, chosenEdge, chosenFace, discardedFace};
|
||||||
|
|
||||||
return <InteractiveSection name={`transfer ${index}`} closable defaultClosed={true}
|
return <InteractiveSection name={`transfer ${index}`} closable defaultClosed={true}
|
||||||
{...{viewObjectsProvider: getEdgeTransferViewObjects, topoObj: context, group3d, category, context}}>
|
{...{viewObjectsProvider: getEdgeTransferViewObjects, topoObj: context, group3d, category, context}}>
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ import {
|
||||||
export function FaceFilterExplorer({connectedToAffectedFaces, allFaces, group3d}) {
|
export function FaceFilterExplorer({connectedToAffectedFaces, allFaces, group3d}) {
|
||||||
connectedToAffectedFaces = connectedToAffectedFaces || [];
|
connectedToAffectedFaces = connectedToAffectedFaces || [];
|
||||||
allFaces = allFaces || [];
|
allFaces = allFaces || [];
|
||||||
let notConnectedToAffectedFaces = allFaces.filter(f => connectedToAffectedFaces.indexOf(f) === -1);
|
const notConnectedToAffectedFaces = allFaces.filter(f => connectedToAffectedFaces.indexOf(f) === -1);
|
||||||
let category = 'face-filter';
|
const category = 'face-filter';
|
||||||
let context = {connectedToAffectedFaces, notConnectedToAffectedFaces};
|
const context = {connectedToAffectedFaces, notConnectedToAffectedFaces};
|
||||||
return <InteractiveSection name='analyzed faces' closable defaultClosed={false}
|
return <InteractiveSection name='analyzed faces' closable defaultClosed={false}
|
||||||
{...{viewObjectsProvider: getFacesViewObjects, topoObj: allFaces, group3d, category, context}}>
|
{...{viewObjectsProvider: getFacesViewObjects, topoObj: allFaces, group3d, category, context}}>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ import {
|
||||||
|
|
||||||
|
|
||||||
export function FaceIntersectionsExplorer({faceIntersection, id, group3d}) {
|
export function FaceIntersectionsExplorer({faceIntersection, id, group3d}) {
|
||||||
let category='face-intersections';
|
const category='face-intersections';
|
||||||
let context = faceIntersection;
|
const context = faceIntersection;
|
||||||
let {faceA, faceB, curve, nodes} = faceIntersection;
|
const {faceA, faceB, curve, nodes} = faceIntersection;
|
||||||
|
|
||||||
return <InteractiveSection name={`intersection ${id}`} closable defaultClosed={true}
|
return <InteractiveSection name={`intersection ${id}`} closable defaultClosed={true}
|
||||||
{...{viewObjectsProvider: faceIntersectionsViewer, topoObj: faceIntersection, group3d, category, context}}>
|
{...{viewObjectsProvider: faceIntersectionsViewer, topoObj: faceIntersection, group3d, category, context}}>
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,13 @@ import {
|
||||||
|
|
||||||
|
|
||||||
export function FaceMergeExplorer({overlappingFacesGroups, group3d}) {
|
export function FaceMergeExplorer({overlappingFacesGroups, group3d}) {
|
||||||
let category = 'overlapping-faces';
|
const category = 'overlapping-faces';
|
||||||
let context = {overlappingFacesGroups};
|
const context = {overlappingFacesGroups};
|
||||||
return <InteractiveSection name='overlapping faces' closable defaultClosed={false}
|
return <InteractiveSection name='overlapping faces' closable defaultClosed={false}
|
||||||
{...{viewObjectsProvider: overlappingFacesViewer, topoObj: overlappingFacesGroups, group3d, category, context}}>
|
{...{viewObjectsProvider: overlappingFacesViewer, topoObj: overlappingFacesGroups, group3d, category, context}}>
|
||||||
|
|
||||||
{ overlappingFacesGroups.map((group, groupIndex) => {
|
{ overlappingFacesGroups.map((group, groupIndex) => {
|
||||||
let [groupA, groupB] = group;
|
const [groupA, groupB] = group;
|
||||||
return <InteractiveSection key={groupIndex} name='merge group' closable defaultClosed={true}
|
return <InteractiveSection key={groupIndex} name='merge group' closable defaultClosed={true}
|
||||||
{...{viewObjectsProvider: overlappingGroupViewer, topoObj: group, group3d, category, context: group}}>
|
{...{viewObjectsProvider: overlappingGroupViewer, topoObj: group, group3d, category, context: group}}>
|
||||||
<InteractiveSection name='from A' closable defaultClosed={false}
|
<InteractiveSection name='from A' closable defaultClosed={false}
|
||||||
|
|
@ -31,7 +31,7 @@ export function FaceMergeExplorer({overlappingFacesGroups, group3d}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function overlappingFacesViewer(group3d, category, context, out, groups) {
|
function overlappingFacesViewer(group3d, category, context, out, groups) {
|
||||||
for (let [groupA, groupB] of groups) {
|
for (const [groupA, groupB] of groups) {
|
||||||
getFacesViewObjects(group3d, category, context, out, groupA);
|
getFacesViewObjects(group3d, category, context, out, groupA);
|
||||||
getFacesViewObjects(group3d, category, context, out, groupB);
|
getFacesViewObjects(group3d, category, context, out, groupB);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,15 +15,15 @@ export default class LoopDetectionExplorer extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {loopDetection: {id, graph, steps, detectedLoops}, group3d} = this.props;
|
const {loopDetection: {id, graph, steps, detectedLoops}, group3d} = this.props;
|
||||||
|
|
||||||
let detectedEdges = new Set();
|
const detectedEdges = new Set();
|
||||||
for (let loop of detectedLoops) {
|
for (const loop of detectedLoops) {
|
||||||
loop.halfEdges.forEach(e => detectedEdges.add(e));
|
loop.halfEdges.forEach(e => detectedEdges.add(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let step = steps[this.state.step];
|
const step = steps[this.state.step];
|
||||||
if (!step) {
|
if (!step) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -39,12 +39,12 @@ export default class LoopDetectionExplorer extends React.PureComponent {
|
||||||
|
|
||||||
|
|
||||||
function backTrack(stepIdx) {
|
function backTrack(stepIdx) {
|
||||||
let looped = new Set();
|
const looped = new Set();
|
||||||
let used = new Set();
|
const used = new Set();
|
||||||
let active = [];
|
let active = [];
|
||||||
|
|
||||||
for (let i = 0; i < stepIdx + 1; i++) {
|
for (let i = 0; i < stepIdx + 1; i++) {
|
||||||
let step = steps[i];
|
const step = steps[i];
|
||||||
switch (step.type) {
|
switch (step.type) {
|
||||||
case 'TRY_LOOP': {
|
case 'TRY_LOOP': {
|
||||||
if (active.length !== 0) {
|
if (active.length !== 0) {
|
||||||
|
|
@ -64,7 +64,7 @@ export default class LoopDetectionExplorer extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let lastActive = active[active.length - 1];
|
const lastActive = active[active.length - 1];
|
||||||
active = new Set(active);
|
active = new Set(active);
|
||||||
return {
|
return {
|
||||||
active, used, looped, lastActive
|
active, used, looped, lastActive
|
||||||
|
|
@ -72,11 +72,11 @@ export default class LoopDetectionExplorer extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
function color(stepIdx) {
|
function color(stepIdx) {
|
||||||
let step = steps[stepIdx];
|
const step = steps[stepIdx];
|
||||||
let {active, used, looped, lastActive} = backTrack(stepIdx);
|
const {active, used, looped, lastActive} = backTrack(stepIdx);
|
||||||
setViewObjectsColor(getGraphViewObjects, group3d, 'loop-detection', detectedEdges, graph, vo => {
|
setViewObjectsColor(getGraphViewObjects, group3d, 'loop-detection', detectedEdges, graph, vo => {
|
||||||
vo.visible = true;
|
vo.visible = true;
|
||||||
let o = vo.__tcad_debug_topoObj;
|
const o = vo.__tcad_debug_topoObj;
|
||||||
if (step.type === 'NEXT_STEP_ANALYSIS') {
|
if (step.type === 'NEXT_STEP_ANALYSIS') {
|
||||||
if (step.winner === o){
|
if (step.winner === o){
|
||||||
return YELLOW
|
return YELLOW
|
||||||
|
|
@ -100,7 +100,7 @@ export default class LoopDetectionExplorer extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
const doStep = nextStepIdx => {
|
const doStep = nextStepIdx => {
|
||||||
let nextStep = steps[nextStepIdx];
|
const nextStep = steps[nextStepIdx];
|
||||||
if (nextStep !== undefined) {
|
if (nextStep !== undefined) {
|
||||||
color(nextStepIdx);
|
color(nextStepIdx);
|
||||||
this.setState({step: nextStepIdx});
|
this.setState({step: nextStepIdx});
|
||||||
|
|
@ -115,20 +115,20 @@ export default class LoopDetectionExplorer extends React.PureComponent {
|
||||||
doStep(this.state.step - 1);
|
doStep(this.state.step - 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
let ctrlProps = {
|
const ctrlProps = {
|
||||||
viewObjectsProvider: getGraphViewObjects, topoObj: graph, group3d, category: 'loop-detection', context: detectedEdges
|
viewObjectsProvider: getGraphViewObjects, topoObj: graph, group3d, category: 'loop-detection', context: detectedEdges
|
||||||
};
|
};
|
||||||
let begin = this.state.step === 0;
|
const begin = this.state.step === 0;
|
||||||
let end = this.state.step === steps.length - 1;
|
const end = this.state.step === steps.length - 1;
|
||||||
|
|
||||||
let controls = <span>
|
const controls = <span>
|
||||||
<Controls {...ctrlProps} />
|
<Controls {...ctrlProps} />
|
||||||
<span className={cx({clickable: !begin, grayed: begin})} onClick={stepBack}><i className='fa fa-fw fa-caret-square-o-left' /> back</span>
|
<span className={cx({clickable: !begin, grayed: begin})} onClick={stepBack}><i className='fa fa-fw fa-caret-square-o-left' /> back</span>
|
||||||
<span className={cx({clickable: !end, grayed: end})} onClick={stepNext}><i className='fa fa-fw fa-caret-square-o-right' /> next</span>
|
<span className={cx({clickable: !end, grayed: end})} onClick={stepNext}><i className='fa fa-fw fa-caret-square-o-right' /> next</span>
|
||||||
<i> step: <b>{this.state.step || '-'}</b></i>
|
<i> step: <b>{this.state.step || '-'}</b></i>
|
||||||
</span>;
|
</span>;
|
||||||
|
|
||||||
let name = <ActiveLabel {...ctrlProps}>loop detection {id}</ActiveLabel>;
|
const name = <ActiveLabel {...ctrlProps}>loop detection {id}</ActiveLabel>;
|
||||||
|
|
||||||
return <Section name={name} closable defaultClosed={true} controls={controls}>
|
return <Section name={name} closable defaultClosed={true} controls={controls}>
|
||||||
{candidates}
|
{candidates}
|
||||||
|
|
@ -143,11 +143,11 @@ export default class LoopDetectionExplorer extends React.PureComponent {
|
||||||
|
|
||||||
|
|
||||||
export function GraphExplorer({graph, group3d, context}) {
|
export function GraphExplorer({graph, group3d, context}) {
|
||||||
let ctrlProps = {
|
const ctrlProps = {
|
||||||
viewObjectsProvider: getGraphViewObjects, topoObj: graph, group3d, category: 'loop-detection', context
|
viewObjectsProvider: getGraphViewObjects, topoObj: graph, group3d, category: 'loop-detection', context
|
||||||
};
|
};
|
||||||
let controls = <Controls {...ctrlProps} />;
|
const controls = <Controls {...ctrlProps} />;
|
||||||
let name = <ActiveLabel {...ctrlProps}>graph</ActiveLabel>;
|
const name = <ActiveLabel {...ctrlProps}>graph</ActiveLabel>;
|
||||||
|
|
||||||
return <Section name={name} tabs={TAB} closable defaultClosed={true} controls={controls}>
|
return <Section name={name} tabs={TAB} closable defaultClosed={true} controls={controls}>
|
||||||
{mapIterable(graph, edge => <EdgeExplorer key={edge.refId} {...{edge, group3d, context}} category='loop-detection'/>)}
|
{mapIterable(graph, edge => <EdgeExplorer key={edge.refId} {...{edge, group3d, context}} category='loop-detection'/>)}
|
||||||
|
|
@ -156,8 +156,8 @@ export function GraphExplorer({graph, group3d, context}) {
|
||||||
|
|
||||||
|
|
||||||
export function DiscardedExplorer({detectedEdges, graph, group3d}) {
|
export function DiscardedExplorer({detectedEdges, graph, group3d}) {
|
||||||
let discardedEdges = new Set(graph);
|
const discardedEdges = new Set(graph);
|
||||||
for (let edge of detectedEdges) {
|
for (const edge of detectedEdges) {
|
||||||
discardedEdges.delete(edge);
|
discardedEdges.delete(edge);
|
||||||
}
|
}
|
||||||
return (discardedEdges.size !== 0 ? <EdgesExplorer edges={Array.from(discardedEdges)} {...{group3d}}
|
return (discardedEdges.size !== 0 ? <EdgesExplorer edges={Array.from(discardedEdges)} {...{group3d}}
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ import {
|
||||||
|
|
||||||
|
|
||||||
export function MarkedEdgesExplorer({markedEdges, group3d}) {
|
export function MarkedEdgesExplorer({markedEdges, group3d}) {
|
||||||
let category='marked-edges';
|
const category='marked-edges';
|
||||||
let context = markedEdges.reduce((acc, v) => {acc[v.edge] = v; return acc}, {});
|
const context = markedEdges.reduce((acc, v) => {acc[v.edge] = v; return acc}, {});
|
||||||
let edges = markedEdges.map(e => e.edge);
|
const edges = markedEdges.map(e => e.edge);
|
||||||
|
|
||||||
return <InteractiveSection name='marked edges' closable defaultClosed={false}
|
return <InteractiveSection name='marked edges' closable defaultClosed={false}
|
||||||
{...{viewObjectsProvider: getEdgesViewObjects, topoObj: edges, group3d, category, context}}>
|
{...{viewObjectsProvider: getEdgesViewObjects, topoObj: edges, group3d, category, context}}>
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ export default class Section extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {name, tabs, closable, defaultClosed, accent, children, captionStyles, controls} = this.props;
|
const {name, tabs, closable, defaultClosed, accent, children, captionStyles, controls} = this.props;
|
||||||
let closed = this.isClosed();
|
const closed = this.isClosed();
|
||||||
return <div className={cx('section', {closable, closed})} style={{paddingLeft: tabs + 'em'}}>
|
return <div className={cx('section', {closable, closed})} style={{paddingLeft: tabs + 'em'}}>
|
||||||
<div className={cx('caption', {accent}, captionStyles)} >
|
<div className={cx('caption', {accent}, captionStyles)} >
|
||||||
<span className='title' onClick={closable ? this.tweakClose : undefined}>
|
<span className='title' onClick={closable ? this.tweakClose : undefined}>
|
||||||
|
|
@ -26,7 +26,7 @@ export default class Section extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
isClosed() {
|
isClosed() {
|
||||||
let {closable, defaultClosed} = this.props;
|
const {closable, defaultClosed} = this.props;
|
||||||
if (!closable) return false;
|
if (!closable) return false;
|
||||||
return closable && (this.state.closed === null ? defaultClosed : this.state.closed)
|
return closable && (this.state.closed === null ? defaultClosed : this.state.closed)
|
||||||
}
|
}
|
||||||
|
|
@ -38,7 +38,7 @@ export default class Section extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapIterator(it, fn) {
|
function mapIterator(it, fn) {
|
||||||
for (let i of it) {
|
for (const i of it) {
|
||||||
fn(i);
|
fn(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,11 @@ import {
|
||||||
export default class ShellExplorer extends React.PureComponent {
|
export default class ShellExplorer extends React.PureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {shell, group3d} = this.props;
|
const {shell, group3d} = this.props;
|
||||||
|
|
||||||
let category='default';
|
const category='default';
|
||||||
let context = null;
|
const context = null;
|
||||||
let faces = shell ? shell.faces : [];
|
const faces = shell ? shell.faces : [];
|
||||||
|
|
||||||
return <InteractiveSection name={`shell ${shell ? shell.refId : 'UNAVAILABLE'}`} closable defaultClosed={false}
|
return <InteractiveSection name={`shell ${shell ? shell.refId : 'UNAVAILABLE'}`} closable defaultClosed={false}
|
||||||
{...{viewObjectsProvider: getFacesViewObjects, topoObj: faces, group3d, category, context}}>
|
{...{viewObjectsProvider: getFacesViewObjects, topoObj: faces, group3d, category, context}}>
|
||||||
|
|
@ -29,18 +29,18 @@ export function FaceExplorer({face, group3d, customName, category, context}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function LoopsExplorer({loops, group3d, name, category, context}) {
|
export function LoopsExplorer({loops, group3d, name, category, context}) {
|
||||||
let ctrlProps = {
|
const ctrlProps = {
|
||||||
viewObjectsProvider: getLoopsViewObjects, topoObj: loops, group3d, category, context
|
viewObjectsProvider: getLoopsViewObjects, topoObj: loops, group3d, category, context
|
||||||
};
|
};
|
||||||
let controls = <Controls {...ctrlProps} />;
|
const controls = <Controls {...ctrlProps} />;
|
||||||
let nameComp = <ActiveLabel {...ctrlProps}>{name}</ActiveLabel>;
|
const nameComp = <ActiveLabel {...ctrlProps}>{name}</ActiveLabel>;
|
||||||
return <Section name={nameComp} tabs={TAB} closable defaultClosed={true} controls={controls}>
|
return <Section name={nameComp} tabs={TAB} closable defaultClosed={true} controls={controls}>
|
||||||
{mapIterable(loops, loop => <LoopExplorer key={loop.refId} {...{loop, group3d, category, context}} />)}
|
{mapIterable(loops, loop => <LoopExplorer key={loop.refId} {...{loop, group3d, category, context}} />)}
|
||||||
</Section>
|
</Section>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function LoopExplorer({loop, group3d, customName, category, context}) {
|
export function LoopExplorer({loop, group3d, customName, category, context}) {
|
||||||
let highlightProps = {
|
const highlightProps = {
|
||||||
viewObjectsProvider: getEdgesViewObjects, topoObj: loop.halfEdges, group3d, category, context
|
viewObjectsProvider: getEdgesViewObjects, topoObj: loop.halfEdges, group3d, category, context
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -52,11 +52,11 @@ export function LoopExplorer({loop, group3d, customName, category, context}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function EdgesExplorer({edges, group3d, name, category, context}) {
|
export function EdgesExplorer({edges, group3d, name, category, context}) {
|
||||||
let ctrlProps = {
|
const ctrlProps = {
|
||||||
viewObjectsProvider: getEdgesViewObjects, topoObj: edges, group3d, category, context
|
viewObjectsProvider: getEdgesViewObjects, topoObj: edges, group3d, category, context
|
||||||
};
|
};
|
||||||
let controls = <Controls {...ctrlProps} />;
|
const controls = <Controls {...ctrlProps} />;
|
||||||
let nameCtrl = <ActiveLabel {...ctrlProps}>{name}</ActiveLabel>;
|
const nameCtrl = <ActiveLabel {...ctrlProps}>{name}</ActiveLabel>;
|
||||||
|
|
||||||
return <Section name={nameCtrl} tabs={TAB} closable defaultClosed={true} controls={controls}>
|
return <Section name={nameCtrl} tabs={TAB} closable defaultClosed={true} controls={controls}>
|
||||||
{mapIterable(edges, edge => <EdgeExplorer key={edge.refId} {...{edge, group3d, category, context}}/>)}
|
{mapIterable(edges, edge => <EdgeExplorer key={edge.refId} {...{edge, group3d, category, context}}/>)}
|
||||||
|
|
@ -64,12 +64,12 @@ export function EdgesExplorer({edges, group3d, name, category, context}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function EdgeExplorer({edge, group3d, customName, category, context}) {
|
export function EdgeExplorer({edge, group3d, customName, category, context}) {
|
||||||
let ctrlProps = {
|
const ctrlProps = {
|
||||||
viewObjectsProvider: getEdgeViewObjects, topoObj: edge, group3d, category, context
|
viewObjectsProvider: getEdgeViewObjects, topoObj: edge, group3d, category, context
|
||||||
};
|
};
|
||||||
let controls = <Controls {...ctrlProps} />;
|
const controls = <Controls {...ctrlProps} />;
|
||||||
let name = <ActiveLabel {...ctrlProps}>{getName('edge', customName, edge)}</ActiveLabel>;
|
const name = <ActiveLabel {...ctrlProps}>{getName('edge', customName, edge)}</ActiveLabel>;
|
||||||
let twin = edge.twin();
|
const twin = edge.twin();
|
||||||
|
|
||||||
return <Section name={name} tabs={TAB} closable defaultClosed={true} controls={controls}>
|
return <Section name={name} tabs={TAB} closable defaultClosed={true} controls={controls}>
|
||||||
{twin && <FR>
|
{twin && <FR>
|
||||||
|
|
@ -86,11 +86,11 @@ export function EdgeExplorer({edge, group3d, customName, category, context}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VertexExplorer({vertex, group3d, customName, category, context}) {
|
export function VertexExplorer({vertex, group3d, customName, category, context}) {
|
||||||
let ctrlProps = {
|
const ctrlProps = {
|
||||||
viewObjectsProvider: getVertexViewObjects, topoObj: vertex, group3d, category, context
|
viewObjectsProvider: getVertexViewObjects, topoObj: vertex, group3d, category, context
|
||||||
};
|
};
|
||||||
let controls = <Controls {...ctrlProps} />;
|
const controls = <Controls {...ctrlProps} />;
|
||||||
let name = <ActiveLabel {...ctrlProps}>{getName('vertex', customName, vertex)}</ActiveLabel>;
|
const name = <ActiveLabel {...ctrlProps}>{getName('vertex', customName, vertex)}</ActiveLabel>;
|
||||||
|
|
||||||
return <Section name={name} closable tabs={TAB} controls={controls} />
|
return <Section name={name} closable tabs={TAB} controls={controls} />
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,9 @@ export function getEdgesViewObjects(group3d, category, context, out, edges) {
|
||||||
export function getViewObjectsComposite(providers) {
|
export function getViewObjectsComposite(providers) {
|
||||||
return function (group3d, category, context, out, objects) {
|
return function (group3d, category, context, out, objects) {
|
||||||
for (let i = 0; i < providers.length; i++) {
|
for (let i = 0; i < providers.length; i++) {
|
||||||
let obj = objects[i];
|
const obj = objects[i];
|
||||||
if (obj) {
|
if (obj) {
|
||||||
let provider = providers[i];
|
const provider = providers[i];
|
||||||
provider(group3d, category, context, out, obj);
|
provider(group3d, category, context, out, obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -39,7 +39,7 @@ export function getViewObjectsComposite(providers) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getEdgeViewObjects = findOrCreate.bind(null, (edge, color) => {
|
export const getEdgeViewObjects = findOrCreate.bind(null, (edge, color) => {
|
||||||
let points = edge.edge.curve.tessellate();
|
const points = edge.edge.curve.tessellate();
|
||||||
if (edge.inverted) {
|
if (edge.inverted) {
|
||||||
points.reverse();
|
points.reverse();
|
||||||
}
|
}
|
||||||
|
|
@ -47,23 +47,23 @@ export const getEdgeViewObjects = findOrCreate.bind(null, (edge, color) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
export const getCurveViewObjects = findOrCreate.bind(null, (curve, color) => {
|
export const getCurveViewObjects = findOrCreate.bind(null, (curve, color) => {
|
||||||
let points = curve.tessellate();
|
const points = curve.tessellate();
|
||||||
let end = curve.point(curve.uMax);
|
const end = curve.point(curve.uMax);
|
||||||
return createDirectedCurve(points, curve.tangentAtPoint(end), end, color)
|
return createDirectedCurve(points, curve.tangentAtPoint(end), end, color)
|
||||||
});
|
});
|
||||||
|
|
||||||
function createDirectedCurve(points, arrowDir, arrowTipPos, color) {
|
function createDirectedCurve(points, arrowDir, arrowTipPos, color) {
|
||||||
|
|
||||||
let obj = new THREE.Object3D();
|
const obj = new THREE.Object3D();
|
||||||
obj.__tcad_debug_materials = [];
|
obj.__tcad_debug_materials = [];
|
||||||
|
|
||||||
let material = new THREE.LineBasicMaterial({color, linewidth: 10});
|
const material = new THREE.LineBasicMaterial({color, linewidth: 10});
|
||||||
const vertices = [];
|
const vertices = [];
|
||||||
|
|
||||||
let edgeLength = 0;
|
let edgeLength = 0;
|
||||||
for (let i = 1; i < points.length; ++i) {
|
for (let i = 1; i < points.length; ++i) {
|
||||||
let a = points[i - 1];
|
const a = points[i - 1];
|
||||||
let b = points[i];
|
const b = points[i];
|
||||||
vertices.push(a.three());
|
vertices.push(a.three());
|
||||||
vertices.push(b.three());
|
vertices.push(b.three());
|
||||||
edgeLength += distanceAB3(a, b);
|
edgeLength += distanceAB3(a, b);
|
||||||
|
|
@ -76,14 +76,14 @@ function createDirectedCurve(points, arrowDir, arrowTipPos, color) {
|
||||||
|
|
||||||
|
|
||||||
let arrowLength = 15;
|
let arrowLength = 15;
|
||||||
let arrowWidth = 0.2 * arrowLength;
|
const arrowWidth = 0.2 * arrowLength;
|
||||||
if (arrowLength > edgeLength * 0.5) {
|
if (arrowLength > edgeLength * 0.5) {
|
||||||
arrowLength = edgeLength * 0.5;
|
arrowLength = edgeLength * 0.5;
|
||||||
}
|
}
|
||||||
let dir = arrowDir;
|
const dir = arrowDir;
|
||||||
let pos = arrowTipPos.minus(dir.multiply(arrowLength * 0.5));
|
const pos = arrowTipPos.minus(dir.multiply(arrowLength * 0.5));
|
||||||
let cone = new THREE.CylinderGeometry( 0, arrowWidth, arrowLength, 10, 1 );
|
const cone = new THREE.CylinderGeometry( 0, arrowWidth, arrowLength, 10, 1 );
|
||||||
let arrow = new THREE.Mesh( cone, new THREE.MeshBasicMaterial( { color} ) );
|
const arrow = new THREE.Mesh( cone, new THREE.MeshBasicMaterial( { color} ) );
|
||||||
if ( dir.y > 0.99999 ) {
|
if ( dir.y > 0.99999 ) {
|
||||||
arrow.quaternion.set( 0, 0, 0, 1 );
|
arrow.quaternion.set( 0, 0, 0, 1 );
|
||||||
} else if ( dir.y < - 0.99999 ) {
|
} else if ( dir.y < - 0.99999 ) {
|
||||||
|
|
@ -107,9 +107,9 @@ export const getPointViewObjects = findOrCreate.bind(null, ({x,y,z}, color) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function createPoint(x,y,z, color) {
|
function createPoint(x,y,z, color) {
|
||||||
let geometry = new THREE.SphereGeometry( 5, 16, 16 );
|
const geometry = new THREE.SphereGeometry( 5, 16, 16 );
|
||||||
let material = new THREE.MeshBasicMaterial( {color} );
|
const material = new THREE.MeshBasicMaterial( {color} );
|
||||||
let sphere = new THREE.Mesh(geometry, material);
|
const sphere = new THREE.Mesh(geometry, material);
|
||||||
sphere.position.x = x;
|
sphere.position.x = x;
|
||||||
sphere.position.y = y;
|
sphere.position.y = y;
|
||||||
sphere.position.z = z;
|
sphere.position.z = z;
|
||||||
|
|
@ -136,7 +136,7 @@ export function setViewObjectsColor(objectsProvider, group3d, category, context,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchViewObjects(objectsProvider, group3d, category, context, topoObj) {
|
export function fetchViewObjects(objectsProvider, group3d, category, context, topoObj) {
|
||||||
let objs = [];
|
const objs = [];
|
||||||
objectsProvider(group3d, category, context, objs, topoObj);
|
objectsProvider(group3d, category, context, objs, topoObj);
|
||||||
return objs;
|
return objs;
|
||||||
}
|
}
|
||||||
|
|
@ -150,7 +150,7 @@ export function getInitColor(category, obj, context) {
|
||||||
return context.has(obj) ? DETECTED_EDGE : DISCARDED_EDGE;
|
return context.has(obj) ? DETECTED_EDGE : DISCARDED_EDGE;
|
||||||
}
|
}
|
||||||
case 'edge-transfer': {
|
case 'edge-transfer': {
|
||||||
let {edge, face, chosenFace, discardedFace, chosenEdge} = context;
|
const {edge, face, chosenFace, discardedFace, chosenEdge} = context;
|
||||||
if (obj === edge) {
|
if (obj === edge) {
|
||||||
return RED;
|
return RED;
|
||||||
} else if (obj.loop.face === face) {
|
} else if (obj.loop.face === face) {
|
||||||
|
|
@ -166,7 +166,7 @@ export function getInitColor(category, obj, context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'face-filter': {
|
case 'face-filter': {
|
||||||
let {connectedToAffectedFaces, notConnectedToAffectedFaces} = context;
|
const {connectedToAffectedFaces, notConnectedToAffectedFaces} = context;
|
||||||
if (connectedToAffectedFaces.indexOf(obj.loop.face) > -1) {
|
if (connectedToAffectedFaces.indexOf(obj.loop.face) > -1) {
|
||||||
return WHITE;
|
return WHITE;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -174,11 +174,11 @@ export function getInitColor(category, obj, context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'marked-edges': {
|
case 'marked-edges': {
|
||||||
let color = context[obj].color;
|
const color = context[obj].color;
|
||||||
return color === undefined ? YELLOW : color;
|
return color === undefined ? YELLOW : color;
|
||||||
}
|
}
|
||||||
case 'face-intersections': {
|
case 'face-intersections': {
|
||||||
let {faceA, faceB} = context;
|
const {faceA, faceB} = context;
|
||||||
if (obj.constructor.name === 'HalfEdge') {
|
if (obj.constructor.name === 'HalfEdge') {
|
||||||
return faceContainsEdge(faceA, obj) ? AQUA : YELLOW;
|
return faceContainsEdge(faceA, obj) ? AQUA : YELLOW;
|
||||||
} else if (obj.constructor.name === 'Vector') {
|
} else if (obj.constructor.name === 'Vector') {
|
||||||
|
|
@ -197,7 +197,7 @@ export function getInitColor(category, obj, context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function faceContainsEdge(face, edge) {
|
function faceContainsEdge(face, edge) {
|
||||||
for (let e of face.edges) {
|
for (const e of face.edges) {
|
||||||
if (e === edge) {
|
if (e === edge) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -207,23 +207,23 @@ function faceContainsEdge(face, edge) {
|
||||||
|
|
||||||
export function mapIterable(it, fn) {
|
export function mapIterable(it, fn) {
|
||||||
const out = [];
|
const out = [];
|
||||||
for (let i of it) {
|
for (const i of it) {
|
||||||
out.push(fn(i));
|
out.push(fn(i));
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function forEach(it, fn) {
|
export function forEach(it, fn) {
|
||||||
for (let i of it) {
|
for (const i of it) {
|
||||||
fn(i);
|
fn(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function createObjectsUpdater(viewObjectsProvider, group3d, category, context, topoObj) {
|
export function createObjectsUpdater(viewObjectsProvider, group3d, category, context, topoObj) {
|
||||||
let getObjects = out => viewObjectsProvider.bind(null, group3d, category, context, out, topoObj)();
|
const getObjects = out => viewObjectsProvider.bind(null, group3d, category, context, out, topoObj)();
|
||||||
return function (func) {
|
return function (func) {
|
||||||
let out = [];
|
const out = [];
|
||||||
getObjects(out);
|
getObjects(out);
|
||||||
out.forEach(func);
|
out.forEach(func);
|
||||||
__DEBUG__.render();
|
__DEBUG__.render();
|
||||||
|
|
@ -231,7 +231,7 @@ export function createObjectsUpdater(viewObjectsProvider, group3d, category, con
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Controls({viewObjectsProvider, group3d, category, context, topoObj}) {
|
export function Controls({viewObjectsProvider, group3d, category, context, topoObj}) {
|
||||||
let applyToAll = createObjectsUpdater(viewObjectsProvider, group3d, category, context, topoObj);
|
const applyToAll = createObjectsUpdater(viewObjectsProvider, group3d, category, context, topoObj);
|
||||||
function tweak() {
|
function tweak() {
|
||||||
let toState = null;
|
let toState = null;
|
||||||
applyToAll(o => {
|
applyToAll(o => {
|
||||||
|
|
@ -251,7 +251,7 @@ export function Controls({viewObjectsProvider, group3d, category, context, topoO
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ActiveLabel({viewObjectsProvider, group3d, category, context, topoObj, children, ...props}) {
|
export function ActiveLabel({viewObjectsProvider, group3d, category, context, topoObj, children, ...props}) {
|
||||||
let applyToAll = createObjectsUpdater(viewObjectsProvider, group3d, category, context, topoObj);
|
const applyToAll = createObjectsUpdater(viewObjectsProvider, group3d, category, context, topoObj);
|
||||||
function onMouseEnter() {
|
function onMouseEnter() {
|
||||||
applyToAll(o => {
|
applyToAll(o => {
|
||||||
if (o.__tcad_debug_last_visible === undefined) {
|
if (o.__tcad_debug_last_visible === undefined) {
|
||||||
|
|
@ -280,9 +280,9 @@ export function ActiveLabel({viewObjectsProvider, group3d, category, context, to
|
||||||
}
|
}
|
||||||
|
|
||||||
export function InteractiveSection({viewObjectsProvider, topoObj, group3d, category, context, name, closable, defaultClosed, children}) {
|
export function InteractiveSection({viewObjectsProvider, topoObj, group3d, category, context, name, closable, defaultClosed, children}) {
|
||||||
let ctrlProps = {viewObjectsProvider, topoObj, group3d, category, context};
|
const ctrlProps = {viewObjectsProvider, topoObj, group3d, category, context};
|
||||||
let controls = <Controls {...ctrlProps} />;
|
const controls = <Controls {...ctrlProps} />;
|
||||||
let nameCtrl = <ActiveLabel {...ctrlProps}>{name}</ActiveLabel>;
|
const nameCtrl = <ActiveLabel {...ctrlProps}>{name}</ActiveLabel>;
|
||||||
return <Section name={nameCtrl} tabs={TAB} {...{closable, defaultClosed, controls}} >
|
return <Section name={nameCtrl} tabs={TAB} {...{closable, defaultClosed, controls}} >
|
||||||
{children}
|
{children}
|
||||||
</Section>
|
</Section>
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ export function BooleanAlgorithm( shellA, shellB, type ) {
|
||||||
type = TYPE.INTERSECT;
|
type = TYPE.INTERSECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
let workingFaces = collectFaces(shellA, shellB);
|
const workingFaces = collectFaces(shellA, shellB);
|
||||||
|
|
||||||
initOperationData(workingFaces);
|
initOperationData(workingFaces);
|
||||||
|
|
||||||
|
|
@ -67,23 +67,23 @@ export function BooleanAlgorithm( shellA, shellB, type ) {
|
||||||
initVertexFactory(shellA, shellB);
|
initVertexFactory(shellA, shellB);
|
||||||
|
|
||||||
intersectEdges(shellA, shellB);
|
intersectEdges(shellA, shellB);
|
||||||
let mergedFaces = mergeOverlappingFaces(shellA, shellB, type);
|
const mergedFaces = mergeOverlappingFaces(shellA, shellB, type);
|
||||||
|
|
||||||
intersectFaces(shellA, shellB, type);
|
intersectFaces(shellA, shellB, type);
|
||||||
|
|
||||||
replaceMergedFaces(workingFaces, mergedFaces);
|
replaceMergedFaces(workingFaces, mergedFaces);
|
||||||
for (let workingFace of workingFaces) {
|
for (const workingFace of workingFaces) {
|
||||||
workingFace.op.initGraph();
|
workingFace.op.initGraph();
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFaceDataForError(workingFaces);
|
checkFaceDataForError(workingFaces);
|
||||||
|
|
||||||
for (let face of workingFaces) {
|
for (const face of workingFaces) {
|
||||||
face.op.detectedLoops = detectLoops(face.surface, face.op);
|
face.op.detectedLoops = detectLoops(face.surface, face.op);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let face of workingFaces) {
|
for (const face of workingFaces) {
|
||||||
for (let loop of face.op.detectedLoops) {
|
for (const loop of face.op.detectedLoops) {
|
||||||
loop.link();
|
loop.link();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +92,7 @@ export function BooleanAlgorithm( shellA, shellB, type ) {
|
||||||
|
|
||||||
let faces = [];
|
let faces = [];
|
||||||
|
|
||||||
for (let face of workingFaces) {
|
for (const face of workingFaces) {
|
||||||
loopsToFaces(face, face.op.detectedLoops, faces);
|
loopsToFaces(face, face.op.detectedLoops, faces);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,9 +114,9 @@ export function BooleanAlgorithm( shellA, shellB, type ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeInvalidLoops(faces) {
|
function removeInvalidLoops(faces) {
|
||||||
let detectedLoopsSet = new Set();
|
const detectedLoopsSet = new Set();
|
||||||
for (let face of faces) {
|
for (const face of faces) {
|
||||||
for (let loop of face.op.detectedLoops) {
|
for (const loop of face.op.detectedLoops) {
|
||||||
detectedLoopsSet.add(loop);
|
detectedLoopsSet.add(loop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -126,7 +126,7 @@ function removeInvalidLoops(faces) {
|
||||||
return !detectedLoopsSet.has(loop);
|
return !detectedLoopsSet.has(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let face of faces) {
|
for (const face of faces) {
|
||||||
face.op.detectedLoops = face.op.detectedLoops.filter(
|
face.op.detectedLoops = face.op.detectedLoops.filter(
|
||||||
loop => loop.halfEdges.find(e => isLoopInvalid(e.twin().loop)) === undefined);
|
loop => loop.halfEdges.find(e => isLoopInvalid(e.twin().loop)) === undefined);
|
||||||
}
|
}
|
||||||
|
|
@ -134,7 +134,7 @@ function removeInvalidLoops(faces) {
|
||||||
|
|
||||||
function replaceMergedFaces(workingFaces, mergedFaces) {
|
function replaceMergedFaces(workingFaces, mergedFaces) {
|
||||||
function addDecayed(he, out) {
|
function addDecayed(he, out) {
|
||||||
let decayed = EdgeSolveData.get(he).decayed;
|
const decayed = EdgeSolveData.get(he).decayed;
|
||||||
if (decayed) {
|
if (decayed) {
|
||||||
decayed.forEach(de => addDecayed(de, out));
|
decayed.forEach(de => addDecayed(de, out));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -144,11 +144,11 @@ function replaceMergedFaces(workingFaces, mergedFaces) {
|
||||||
filterInPlace(workingFaces, face =>
|
filterInPlace(workingFaces, face =>
|
||||||
mergedFaces.find(({originFaces}) => originFaces.indexOf(face) > -1) === undefined
|
mergedFaces.find(({originFaces}) => originFaces.indexOf(face) > -1) === undefined
|
||||||
);
|
);
|
||||||
for (let {facePrototypes, originFaces} of mergedFaces) {
|
for (const {facePrototypes, originFaces} of mergedFaces) {
|
||||||
for (let {loops, surface} of facePrototypes) {
|
for (const {loops, surface} of facePrototypes) {
|
||||||
let fakeFace = new Face(surface);
|
const fakeFace = new Face(surface);
|
||||||
for (let loop of loops) {
|
for (const loop of loops) {
|
||||||
let actualHalfEdges = [];
|
const actualHalfEdges = [];
|
||||||
loop.halfEdges.forEach(he => addDecayed(he, actualHalfEdges));
|
loop.halfEdges.forEach(he => addDecayed(he, actualHalfEdges));
|
||||||
loop.halfEdges = actualHalfEdges;
|
loop.halfEdges = actualHalfEdges;
|
||||||
fakeFace.innerLoops.push(loop);
|
fakeFace.innerLoops.push(loop);
|
||||||
|
|
@ -157,7 +157,7 @@ function replaceMergedFaces(workingFaces, mergedFaces) {
|
||||||
}
|
}
|
||||||
initOperationDataForFace(fakeFace);
|
initOperationDataForFace(fakeFace);
|
||||||
workingFaces.push(fakeFace);
|
workingFaces.push(fakeFace);
|
||||||
for (let originFace of originFaces) {
|
for (const originFace of originFaces) {
|
||||||
originFace.op.newEdges.forEach(e => addNewEdge(fakeFace, e));
|
originFace.op.newEdges.forEach(e => addNewEdge(fakeFace, e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -165,7 +165,7 @@ function replaceMergedFaces(workingFaces, mergedFaces) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareWorkingCopy(_shell) {
|
function prepareWorkingCopy(_shell) {
|
||||||
let workingCopy = _shell.clone();
|
const workingCopy = _shell.clone();
|
||||||
setAnalysisFace(_shell, workingCopy);
|
setAnalysisFace(_shell, workingCopy);
|
||||||
cleanUpOperationData(workingCopy);
|
cleanUpOperationData(workingCopy);
|
||||||
return workingCopy;
|
return workingCopy;
|
||||||
|
|
@ -224,7 +224,7 @@ function findOverlappingFaces(shellA, shellB) {
|
||||||
function pointOnFace(face, pt) {
|
function pointOnFace(face, pt) {
|
||||||
return face.env2D().pip(face.surface.workingPoint(pt)).inside;
|
return face.env2D().pip(face.surface.workingPoint(pt)).inside;
|
||||||
}
|
}
|
||||||
for (let e1 of face1.edges) {
|
for (const e1 of face1.edges) {
|
||||||
if (pointOnFace(face2, e1.vertexA.point)) {
|
if (pointOnFace(face2, e1.vertexA.point)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -232,8 +232,8 @@ function findOverlappingFaces(shellA, shellB) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function overlaps(face1, face2) {
|
function overlaps(face1, face2) {
|
||||||
let ss1 = face1.surface.simpleSurface;
|
const ss1 = face1.surface.simpleSurface;
|
||||||
let ss2 = face2.surface.simpleSurface;
|
const ss2 = face2.surface.simpleSurface;
|
||||||
if (ss1 !== null && ss2 !== null && ss1.TYPE === 'plane' && ss1.TYPE === ss2.TYPE &&
|
if (ss1 !== null && ss2 !== null && ss1.TYPE === 'plane' && ss1.TYPE === ss2.TYPE &&
|
||||||
ss1.coplanarUnsigned(ss2)) {
|
ss1.coplanarUnsigned(ss2)) {
|
||||||
return overlapsImpl(face1, face2) || overlapsImpl(face2, face1);
|
return overlapsImpl(face1, face2) || overlapsImpl(face2, face1);
|
||||||
|
|
@ -241,10 +241,10 @@ function findOverlappingFaces(shellA, shellB) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let overlapGroups = [];
|
const overlapGroups = [];
|
||||||
|
|
||||||
for (let faceA of shellA.faces) {
|
for (const faceA of shellA.faces) {
|
||||||
for (let faceB of shellB.faces) {
|
for (const faceB of shellB.faces) {
|
||||||
if (DEBUG.FACE_MERGE) {
|
if (DEBUG.FACE_MERGE) {
|
||||||
__DEBUG__.Clear();
|
__DEBUG__.Clear();
|
||||||
__DEBUG__.AddFace(faceA, 0x0000ff);
|
__DEBUG__.AddFace(faceA, 0x0000ff);
|
||||||
|
|
@ -267,28 +267,28 @@ function findOverlappingFaces(shellA, shellB) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeOverlappingFaces(shellA, shellB, opType) {
|
function mergeOverlappingFaces(shellA, shellB, opType) {
|
||||||
let groups = findOverlappingFaces(shellA, shellB);
|
const groups = findOverlappingFaces(shellA, shellB);
|
||||||
BREP_DEBUG.setOverlappingFaces(groups);
|
BREP_DEBUG.setOverlappingFaces(groups);
|
||||||
let mergedFaces = [];
|
const mergedFaces = [];
|
||||||
for (let [groupA, groupB] of groups) {
|
for (const [groupA, groupB] of groups) {
|
||||||
let faceMergeInfo = mergeFaces(Array.from(groupA), Array.from(groupB), opType);
|
const faceMergeInfo = mergeFaces(Array.from(groupA), Array.from(groupB), opType);
|
||||||
mergedFaces.push(faceMergeInfo);
|
mergedFaces.push(faceMergeInfo);
|
||||||
}
|
}
|
||||||
return mergedFaces;
|
return mergedFaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeFaces(facesA, facesB, opType) {
|
function mergeFaces(facesA, facesB, opType) {
|
||||||
let originFaces = [...facesA, ...facesB];
|
const originFaces = [...facesA, ...facesB];
|
||||||
let allPoints = [];
|
const allPoints = [];
|
||||||
|
|
||||||
for (let face of originFaces) {
|
for (const face of originFaces) {
|
||||||
for (let e of face.edges) {
|
for (const e of face.edges) {
|
||||||
allPoints.push(e.vertexA.point);
|
allPoints.push(e.vertexA.point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let valid = new Set();
|
const valid = new Set();
|
||||||
let invalid = new Set();
|
const invalid = new Set();
|
||||||
|
|
||||||
function classify(inside, testee) {
|
function classify(inside, testee) {
|
||||||
if (inside && opType === TYPE.INTERSECT) {
|
if (inside && opType === TYPE.INTERSECT) {
|
||||||
|
|
@ -310,7 +310,7 @@ function mergeFaces(facesA, facesB, opType) {
|
||||||
|
|
||||||
function invalidate(faceA, faceB) {
|
function invalidate(faceA, faceB) {
|
||||||
|
|
||||||
let coincidentEdges = new Set();
|
const coincidentEdges = new Set();
|
||||||
|
|
||||||
function checkCoincidentEdges(edgeA, edgeB) {
|
function checkCoincidentEdges(edgeA, edgeB) {
|
||||||
if (isSameEdge(edgeA, edgeB)) {
|
if (isSameEdge(edgeA, edgeB)) {
|
||||||
|
|
@ -322,8 +322,8 @@ function mergeFaces(facesA, facesB, opType) {
|
||||||
if (edgeA.vertexA === edgeB.vertexA) {
|
if (edgeA.vertexA === edgeB.vertexA) {
|
||||||
// chooseBetweenEqualEdges();
|
// chooseBetweenEqualEdges();
|
||||||
// canEdgeBeTransferred(edge, face, opType)
|
// canEdgeBeTransferred(edge, face, opType)
|
||||||
let faceAAdjacent = edgeA.twin().loop.face;
|
const faceAAdjacent = edgeA.twin().loop.face;
|
||||||
let faceBAdjacent = edgeB.twin().loop.face;
|
const faceBAdjacent = edgeB.twin().loop.face;
|
||||||
if (faceAAdjacent.op.overlaps && faceAAdjacent.op.overlaps.has(faceBAdjacent)) {
|
if (faceAAdjacent.op.overlaps && faceAAdjacent.op.overlaps.has(faceBAdjacent)) {
|
||||||
invalid.add(edgeB);
|
invalid.add(edgeB);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -345,7 +345,7 @@ function mergeFaces(facesA, facesB, opType) {
|
||||||
|
|
||||||
|
|
||||||
function invalidateEdge(face, edge) {
|
function invalidateEdge(face, edge) {
|
||||||
let pt = edge.edge.curve.middlePoint();
|
const pt = edge.edge.curve.middlePoint();
|
||||||
if (face.rayCast(pt).inside) {
|
if (face.rayCast(pt).inside) {
|
||||||
markEdgeTransferred(edge.edge);
|
markEdgeTransferred(edge.edge);
|
||||||
if (canEdgeBeTransferred(edge.twin(), face, opType)) {
|
if (canEdgeBeTransferred(edge.twin(), face, opType)) {
|
||||||
|
|
@ -357,7 +357,7 @@ function mergeFaces(facesA, facesB, opType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function invalidateEdges(faceX, faceY) {
|
function invalidateEdges(faceX, faceY) {
|
||||||
for (let edgeX of faceX.edges) {
|
for (const edgeX of faceX.edges) {
|
||||||
if (coincidentEdges.has(edgeX)) {
|
if (coincidentEdges.has(edgeX)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -365,8 +365,8 @@ function mergeFaces(facesA, facesB, opType) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let edgeA of faceA.edges) {
|
for (const edgeA of faceA.edges) {
|
||||||
for (let edgeB of faceB.edges) {
|
for (const edgeB of faceB.edges) {
|
||||||
checkCoincidentEdges(edgeA, edgeB);
|
checkCoincidentEdges(edgeA, edgeB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -375,21 +375,21 @@ function mergeFaces(facesA, facesB, opType) {
|
||||||
invalidateEdges(faceB, faceA);
|
invalidateEdges(faceB, faceA);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let faceA of facesA) {
|
for (const faceA of facesA) {
|
||||||
for (let faceB of facesB) {
|
for (const faceB of facesB) {
|
||||||
invalidate(faceA, faceB);
|
invalidate(faceA, faceB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let facePrototypes = [];
|
const facePrototypes = [];
|
||||||
let leftovers = null;
|
let leftovers = null;
|
||||||
for (let referenceFace of originFaces) {
|
for (const referenceFace of originFaces) {
|
||||||
|
|
||||||
let graph = new EdgeGraph();
|
const graph = new EdgeGraph();
|
||||||
for (let face of originFaces) {
|
for (const face of originFaces) {
|
||||||
for (let edge of face.edges) {
|
for (const edge of face.edges) {
|
||||||
if (!invalid.has(edge) && (leftovers == null || leftovers.has(edge))) {
|
if (!invalid.has(edge) && (leftovers == null || leftovers.has(edge))) {
|
||||||
graph.add(edge);
|
graph.add(edge);
|
||||||
}
|
}
|
||||||
|
|
@ -397,10 +397,10 @@ function mergeFaces(facesA, facesB, opType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
leftovers = new Set(graph.graphEdges);
|
leftovers = new Set(graph.graphEdges);
|
||||||
let detectedLoops = detectLoops(referenceFace.surface, graph);
|
const detectedLoops = detectLoops(referenceFace.surface, graph);
|
||||||
|
|
||||||
for (let loop of detectedLoops) {
|
for (const loop of detectedLoops) {
|
||||||
for (let edge of loop.halfEdges) {
|
for (const edge of loop.halfEdges) {
|
||||||
// EdgeSolveData.setPriority(edge, 1);
|
// EdgeSolveData.setPriority(edge, 1);
|
||||||
leftovers.delete(edge);
|
leftovers.delete(edge);
|
||||||
}
|
}
|
||||||
|
|
@ -423,16 +423,16 @@ function mergeFaces(facesA, facesB, opType) {
|
||||||
|
|
||||||
export function mergeVertices(shell1, shell2) {
|
export function mergeVertices(shell1, shell2) {
|
||||||
const toSwap = new Map();
|
const toSwap = new Map();
|
||||||
for (let v1 of shell1.vertices) {
|
for (const v1 of shell1.vertices) {
|
||||||
for (let v2 of shell2.vertices) {
|
for (const v2 of shell2.vertices) {
|
||||||
if (veq(v1.point, v2.point)) {
|
if (veq(v1.point, v2.point)) {
|
||||||
toSwap.set(v2, v1);
|
toSwap.set(v2, v1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let face of shell2.faces) {
|
for (const face of shell2.faces) {
|
||||||
for (let h of face.edges) {
|
for (const h of face.edges) {
|
||||||
const aSwap = toSwap.get(h.vertexA);
|
const aSwap = toSwap.get(h.vertexA);
|
||||||
const bSwap = toSwap.get(h.vertexB);
|
const bSwap = toSwap.get(h.vertexB);
|
||||||
if (aSwap) {
|
if (aSwap) {
|
||||||
|
|
@ -448,7 +448,7 @@ export function mergeVertices(shell1, shell2) {
|
||||||
function filterFaces(faces) {
|
function filterFaces(faces) {
|
||||||
|
|
||||||
function doesFaceContainNewEdge(face) {
|
function doesFaceContainNewEdge(face) {
|
||||||
for (let e of face.edges) {
|
for (const e of face.edges) {
|
||||||
if (getPriority(e) > 0 || getPriority(e.twin()) > 0 ||
|
if (getPriority(e) > 0 || getPriority(e.twin()) > 0 ||
|
||||||
EdgeSolveData.get(e).affected === true) {
|
EdgeSolveData.get(e).affected === true) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -458,7 +458,7 @@ function filterFaces(faces) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const resultSet = new Set();
|
const resultSet = new Set();
|
||||||
for (let face of faces) {
|
for (const face of faces) {
|
||||||
// __DEBUG__.Clear();
|
// __DEBUG__.Clear();
|
||||||
// __DEBUG__.AddFace(face);
|
// __DEBUG__.AddFace(face);
|
||||||
traverseFaces(face, (it) => {
|
traverseFaces(face, (it) => {
|
||||||
|
|
@ -483,9 +483,9 @@ function traverseFaces(face, callback) {
|
||||||
if (callback(face) === true) {
|
if (callback(face) === true) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (let loop of face.loops) {
|
for (const loop of face.loops) {
|
||||||
for (let halfEdge of loop.halfEdges) {
|
for (const halfEdge of loop.halfEdges) {
|
||||||
let twinFace = halfEdge.twin().loop.face;
|
const twinFace = halfEdge.twin().loop.face;
|
||||||
if (twinFace === null) {
|
if (twinFace === null) {
|
||||||
//this happened because there is no face created for a valid and legit detected loop
|
//this happened because there is no face created for a valid and legit detected loop
|
||||||
throw new CadError({
|
throw new CadError({
|
||||||
|
|
@ -503,25 +503,25 @@ function traverseFaces(face, callback) {
|
||||||
|
|
||||||
export function loopsToFaces(originFace, loops, out) {
|
export function loopsToFaces(originFace, loops, out) {
|
||||||
const newFaces = evolveFace(originFace, loops);
|
const newFaces = evolveFace(originFace, loops);
|
||||||
for (let newFace of newFaces) {
|
for (const newFace of newFaces) {
|
||||||
out.push(newFace);
|
out.push(newFace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function collectFaces(shellA, shellB) {
|
function collectFaces(shellA, shellB) {
|
||||||
function collect(shell, out) {
|
function collect(shell, out) {
|
||||||
for (let face of shell.faces) {
|
for (const face of shell.faces) {
|
||||||
out.push(face);
|
out.push(face);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let out = [];
|
const out = [];
|
||||||
collect(shellA, out);
|
collect(shellA, out);
|
||||||
collect(shellB, out);
|
collect(shellB, out);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
function initOperationData(faces) {
|
function initOperationData(faces) {
|
||||||
for (let face of faces) {
|
for (const face of faces) {
|
||||||
initOperationDataForFace(face);
|
initOperationDataForFace(face);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -531,9 +531,9 @@ function initOperationDataForFace(face) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanUpOperationData(shell) {
|
function cleanUpOperationData(shell) {
|
||||||
for (let face of shell.faces) {
|
for (const face of shell.faces) {
|
||||||
face.op = null;
|
face.op = null;
|
||||||
for (let he of face.edges) {
|
for (const he of face.edges) {
|
||||||
EdgeSolveData.clear(he);
|
EdgeSolveData.clear(he);
|
||||||
delete he.edge.data[MY];
|
delete he.edge.data[MY];
|
||||||
}
|
}
|
||||||
|
|
@ -548,7 +548,7 @@ function findMaxTurningLeft(pivotEdge, edges, surface) {
|
||||||
const pivot = pivotEdge.tangent(pivotEdge.vertexB.point).negate();
|
const pivot = pivotEdge.tangent(pivotEdge.vertexB.point).negate();
|
||||||
const normal = surface.normal(pivotEdge.vertexB.point);
|
const normal = surface.normal(pivotEdge.vertexB.point);
|
||||||
edges.sort((e1, e2) => {
|
edges.sort((e1, e2) => {
|
||||||
let delta = leftTurningMeasure(pivot, edgeVector(e1), normal) - leftTurningMeasure(pivot, edgeVector(e2), normal);
|
const delta = leftTurningMeasure(pivot, edgeVector(e1), normal) - leftTurningMeasure(pivot, edgeVector(e2), normal);
|
||||||
if (ueq(delta, 0)) {
|
if (ueq(delta, 0)) {
|
||||||
return getPriority(e2) - getPriority(e1);
|
return getPriority(e2) - getPriority(e1);
|
||||||
}
|
}
|
||||||
|
|
@ -571,18 +571,18 @@ function leftTurningMeasure(v1, v2, normal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function intersectEdges(shell1, shell2) {
|
function intersectEdges(shell1, shell2) {
|
||||||
let isecs = new Map();
|
const isecs = new Map();
|
||||||
function addIsesc(e, params) {
|
function addIsesc(e, params) {
|
||||||
let allParams = isecs.get(e);
|
const allParams = isecs.get(e);
|
||||||
if (!allParams) {
|
if (!allParams) {
|
||||||
isecs.set(e, params);
|
isecs.set(e, params);
|
||||||
} else {
|
} else {
|
||||||
params.forEach(p => allParams.push(p));
|
params.forEach(p => allParams.push(p));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let e1 of shell1.edges) {
|
for (const e1 of shell1.edges) {
|
||||||
for (let e2 of shell2.edges) {
|
for (const e2 of shell2.edges) {
|
||||||
let points = e1.curve.intersectCurve(e2.curve, TOLERANCE);
|
const points = e1.curve.intersectCurve(e2.curve, TOLERANCE);
|
||||||
if (points.length !== 0) {
|
if (points.length !== 0) {
|
||||||
const vertexHolder = [];
|
const vertexHolder = [];
|
||||||
addIsesc(e1, points.map( ({u0: u, p0: p}) => ({u, p, vertexHolder}) ));
|
addIsesc(e1, points.map( ({u0: u, p0: p}) => ({u, p, vertexHolder}) ));
|
||||||
|
|
@ -590,17 +590,17 @@ function intersectEdges(shell1, shell2) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let [e, points] of isecs) {
|
for (const [e, points] of isecs) {
|
||||||
points.sort((p1, p2) => p1.u - p2.u);
|
points.sort((p1, p2) => p1.u - p2.u);
|
||||||
for (let {u, vertexHolder} of points ) {
|
for (const {u, vertexHolder} of points ) {
|
||||||
if (!vertexHolder[0]) {
|
if (!vertexHolder[0]) {
|
||||||
vertexHolder[0] = vertexFactory.create(e.curve.point(u));
|
vertexHolder[0] = vertexFactory.create(e.curve.point(u));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let [e, points] of isecs) {
|
for (let [e, points] of isecs) {
|
||||||
for (let {vertexHolder} of points ) {
|
for (const {vertexHolder} of points ) {
|
||||||
let split = splitEdgeByVertex(e, vertexHolder[0]);
|
const split = splitEdgeByVertex(e, vertexHolder[0]);
|
||||||
if (split !== null) {
|
if (split !== null) {
|
||||||
e = split[1];
|
e = split[1];
|
||||||
}
|
}
|
||||||
|
|
@ -609,17 +609,17 @@ function intersectEdges(shell1, shell2) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function fixCurveDirection(curve, surface1, surface2, operationType) {
|
function fixCurveDirection(curve, surface1, surface2, operationType) {
|
||||||
let point = curve.middlePoint();
|
const point = curve.middlePoint();
|
||||||
let tangent = curve.tangentAtPoint(point);
|
const tangent = curve.tangentAtPoint(point);
|
||||||
let normal1 = surface1.normal(point);
|
const normal1 = surface1.normal(point);
|
||||||
let normal2 = surface2.normal(point);
|
const normal2 = surface2.normal(point);
|
||||||
|
|
||||||
let expectedDirection = normal1.cross(normal2);
|
const expectedDirection = normal1.cross(normal2);
|
||||||
|
|
||||||
if (operationType === TYPE.UNION) {
|
if (operationType === TYPE.UNION) {
|
||||||
expectedDirection._negate();
|
expectedDirection._negate();
|
||||||
}
|
}
|
||||||
let sameAsExpected = expectedDirection.dot(tangent) > 0;
|
const sameAsExpected = expectedDirection.dot(tangent) > 0;
|
||||||
if (!sameAsExpected) {
|
if (!sameAsExpected) {
|
||||||
curve = curve.invert();
|
curve = curve.invert();
|
||||||
}
|
}
|
||||||
|
|
@ -628,8 +628,8 @@ function fixCurveDirection(curve, surface1, surface2, operationType) {
|
||||||
|
|
||||||
//TODO: extract to a unit test
|
//TODO: extract to a unit test
|
||||||
function newEdgeDirectionValidityTest(e, curve) {
|
function newEdgeDirectionValidityTest(e, curve) {
|
||||||
let point = e.halfEdge1.vertexA.point;
|
const point = e.halfEdge1.vertexA.point;
|
||||||
let tangent = curve.tangentAtPoint(point);
|
const tangent = curve.tangentAtPoint(point);
|
||||||
assert('tangent of originated curve and first halfEdge should be the same', vectorsEqual(tangent, e.halfEdge1.tangent(point)));
|
assert('tangent of originated curve and first halfEdge should be the same', vectorsEqual(tangent, e.halfEdge1.tangent(point)));
|
||||||
assert('tangent of originated curve and second halfEdge should be the opposite', vectorsEqual(tangent._negate(), e.halfEdge2.tangent(point)));
|
assert('tangent of originated curve and second halfEdge should be the opposite', vectorsEqual(tangent._negate(), e.halfEdge2.tangent(point)));
|
||||||
}
|
}
|
||||||
|
|
@ -653,7 +653,7 @@ function intersectFaces(shellA, shellB, operationType) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let curves = faceA.surface.intersectSurface(faceB.surface);
|
const curves = faceA.surface.intersectSurface(faceB.surface);
|
||||||
|
|
||||||
for (let curve of curves) {
|
for (let curve of curves) {
|
||||||
if (DEBUG.FACE_FACE_INTERSECTION) {
|
if (DEBUG.FACE_FACE_INTERSECTION) {
|
||||||
|
|
@ -687,25 +687,25 @@ function intersectFaces(shellA, shellB, operationType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function chooseBetweenEqualEdges(edgeA, edgeB, operationType) {
|
function chooseBetweenEqualEdges(edgeA, edgeB, operationType) {
|
||||||
let twinA = edgeA.twin();
|
const twinA = edgeA.twin();
|
||||||
let twinB = edgeB.twin();
|
const twinB = edgeB.twin();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function canEdgeBeTransferred(edge, face, operationType) {
|
function canEdgeBeTransferred(edge, face, operationType) {
|
||||||
let testPoint = edge.edge.curve.middlePoint();
|
const testPoint = edge.edge.curve.middlePoint();
|
||||||
let edgeTangent = edge.tangent(testPoint);
|
const edgeTangent = edge.tangent(testPoint);
|
||||||
let edgeFaceNormal = edge.loop.face.surface.normal(testPoint);
|
const edgeFaceNormal = edge.loop.face.surface.normal(testPoint);
|
||||||
let edgeFaceDir = edgeFaceNormal.cross(edgeTangent);
|
const edgeFaceDir = edgeFaceNormal.cross(edgeTangent);
|
||||||
let faceNormal = face.surface.normal(testPoint);
|
const faceNormal = face.surface.normal(testPoint);
|
||||||
let outsideMeasure = edgeFaceDir.dot(faceNormal);
|
const outsideMeasure = edgeFaceDir.dot(faceNormal);
|
||||||
|
|
||||||
if (eq(outsideMeasure, 0)) {
|
if (eq(outsideMeasure, 0)) {
|
||||||
throw 'this case should be considered before calling this method';
|
throw 'this case should be considered before calling this method';
|
||||||
// return undefined;
|
// return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
let outside = outsideMeasure > 0;
|
const outside = outsideMeasure > 0;
|
||||||
return (operationType === TYPE.INTERSECT) !== outside;
|
return (operationType === TYPE.INTERSECT) !== outside;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -714,15 +714,15 @@ export function chooseValidEdge(edge, face, operationType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function transferEdges(faceSource, faceDest, operationType) {
|
function transferEdges(faceSource, faceDest, operationType) {
|
||||||
for (let loop of faceSource.loops) {
|
for (const loop of faceSource.loops) {
|
||||||
for (let edge of loop.halfEdges) {
|
for (const edge of loop.halfEdges) {
|
||||||
if (isEdgeTransferred(edge.edge)) {
|
if (isEdgeTransferred(edge.edge)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (edgeCollinearToFace(edge, faceDest)) {
|
if (edgeCollinearToFace(edge, faceDest)) {
|
||||||
let validEdge = chooseValidEdge(edge, faceDest, operationType);
|
const validEdge = chooseValidEdge(edge, faceDest, operationType);
|
||||||
BREP_DEBUG.transferEdge(edge, faceDest, validEdge);
|
BREP_DEBUG.transferEdge(edge, faceDest, validEdge);
|
||||||
let twin = validEdge.twin();
|
const twin = validEdge.twin();
|
||||||
twin.loop.face.op.markTransferredFrom(twin);
|
twin.loop.face.op.markTransferredFrom(twin);
|
||||||
markEdgeTransferred(twin.edge);
|
markEdgeTransferred(twin.edge);
|
||||||
addNewEdge(faceDest, twin);
|
addNewEdge(faceDest, twin);
|
||||||
|
|
@ -750,7 +750,7 @@ function nodeByPoint(nodes, point, u, curve, vertex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasCoincidentEdge(curve, face) {
|
function hasCoincidentEdge(curve, face) {
|
||||||
for (let edge of face.edges) {
|
for (const edge of face.edges) {
|
||||||
if (curveAndEdgeCoincident(curve, edge)) {
|
if (curveAndEdgeCoincident(curve, edge)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -759,24 +759,24 @@ function hasCoincidentEdge(curve, face) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function collectNodesOfIntersectionOfFace(curve, face, nodes, operand) {
|
function collectNodesOfIntersectionOfFace(curve, face, nodes, operand) {
|
||||||
for (let loop of face.loops) {
|
for (const loop of face.loops) {
|
||||||
collectNodesOfIntersection(curve, loop, nodes, operand);
|
collectNodesOfIntersection(curve, loop, nodes, operand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function collectNodesOfIntersection(curve, loop, nodes, operand) {
|
function collectNodesOfIntersection(curve, loop, nodes, operand) {
|
||||||
// __DEBUG__.AddCurve(curve, 0xffffff);
|
// __DEBUG__.AddCurve(curve, 0xffffff);
|
||||||
let skippedEnclosures = new Set();
|
const skippedEnclosures = new Set();
|
||||||
|
|
||||||
let encloses = loop.encloses;
|
const encloses = loop.encloses;
|
||||||
for (let [a, b, v] of encloses) {
|
for (const [a, b, v] of encloses) {
|
||||||
if (skippedEnclosures.has(v)) {
|
if (skippedEnclosures.has(v)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (curve.passesThrough(v.point)) {
|
if (curve.passesThrough(v.point)) {
|
||||||
let classification = isCurveEntersEnclose(curve, a, b);
|
const classification = isCurveEntersEnclose(curve, a, b);
|
||||||
if (classification === ENCLOSE_CLASSIFICATION.ENTERS || classification === ENCLOSE_CLASSIFICATION.LEAVES) {
|
if (classification === ENCLOSE_CLASSIFICATION.ENTERS || classification === ENCLOSE_CLASSIFICATION.LEAVES) {
|
||||||
let node = nodeByPoint(nodes, v.point, undefined, curve, v);
|
const node = nodeByPoint(nodes, v.point, undefined, curve, v);
|
||||||
if (classification === ENCLOSE_CLASSIFICATION.ENTERS) {
|
if (classification === ENCLOSE_CLASSIFICATION.ENTERS) {
|
||||||
node.enters[operand] = true;
|
node.enters[operand] = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -785,7 +785,7 @@ function collectNodesOfIntersection(curve, loop, nodes, operand) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let edge of loop.halfEdges) {
|
for (const edge of loop.halfEdges) {
|
||||||
intersectCurveWithEdge(curve, edge, nodes, operand);
|
intersectCurveWithEdge(curve, edge, nodes, operand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -794,16 +794,16 @@ function intersectCurveWithEdge(curve, edge, nodes, operand) {
|
||||||
// __DEBUG__.AddCurve(curve, 0xffffff);
|
// __DEBUG__.AddCurve(curve, 0xffffff);
|
||||||
// __DEBUG__.AddHalfEdge(edge, 0xff00ff);
|
// __DEBUG__.AddHalfEdge(edge, 0xff00ff);
|
||||||
const points = edge.edge.curve.intersectCurve(curve);
|
const points = edge.edge.curve.intersectCurve(curve);
|
||||||
for (let point of points) {
|
for (const point of points) {
|
||||||
const {u0, u1} = point;
|
const {u0, u1} = point;
|
||||||
let existing = vertexFactory.find(point.p0);
|
const existing = vertexFactory.find(point.p0);
|
||||||
if (existing !== null) {
|
if (existing !== null) {
|
||||||
// vertex already exists, means either we hit an end of edge and this case is handled by enclosure analysis
|
// vertex already exists, means either we hit an end of edge and this case is handled by enclosure analysis
|
||||||
//
|
//
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let node = nodeByPoint(nodes, point.p0, u1, undefined, null);
|
const node = nodeByPoint(nodes, point.p0, u1, undefined, null);
|
||||||
if (isCurveEntersEdgeAtPoint(curve, edge, node.point)) {
|
if (isCurveEntersEdgeAtPoint(curve, edge, node.point)) {
|
||||||
node.enters[operand] = true;
|
node.enters[operand] = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -821,7 +821,7 @@ function split(nodes, curve, result, faceA, faceB) {
|
||||||
|
|
||||||
nodes.sort((n1, n2) => n1.u - n2.u);
|
nodes.sort((n1, n2) => n1.u - n2.u);
|
||||||
|
|
||||||
let initNode = nodes[0];
|
const initNode = nodes[0];
|
||||||
|
|
||||||
// __DEBUG__.Clear();
|
// __DEBUG__.Clear();
|
||||||
// __DEBUG__.AddFace(faceA);
|
// __DEBUG__.AddFace(faceA);
|
||||||
|
|
@ -831,15 +831,15 @@ function split(nodes, curve, result, faceA, faceB) {
|
||||||
let insideA = faceA.analysisFace.rayCast(initNode.point).strictInside;
|
let insideA = faceA.analysisFace.rayCast(initNode.point).strictInside;
|
||||||
let insideB = faceB.analysisFace.rayCast(initNode.point).strictInside;
|
let insideB = faceB.analysisFace.rayCast(initNode.point).strictInside;
|
||||||
let inNode = null;
|
let inNode = null;
|
||||||
let edgesToSplits = new Map();
|
const edgesToSplits = new Map();
|
||||||
function checkNodeForEdgeSplit(node) {
|
function checkNodeForEdgeSplit(node) {
|
||||||
if (node.edgeSplitInfo !== null) {
|
if (node.edgeSplitInfo !== null) {
|
||||||
addToListInMap(edgesToSplits, node.edgeSplitInfo.edge.edge, node);
|
addToListInMap(edgesToSplits, node.edgeSplitInfo.edge.edge, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let node of nodes) {
|
for (const node of nodes) {
|
||||||
let wasInside = insideA && insideB;
|
const wasInside = insideA && insideB;
|
||||||
let hadLeft = false;
|
let hadLeft = false;
|
||||||
if (node.enters[A] === true) {
|
if (node.enters[A] === true) {
|
||||||
insideA = true;
|
insideA = true;
|
||||||
|
|
@ -860,8 +860,8 @@ function split(nodes, curve, result, faceA, faceB) {
|
||||||
|
|
||||||
if (wasInside && hadLeft) {
|
if (wasInside && hadLeft) {
|
||||||
let edgeCurve = curve;
|
let edgeCurve = curve;
|
||||||
let vertexA = inNode.vertex();
|
const vertexA = inNode.vertex();
|
||||||
let vertexB = node.vertex();
|
const vertexB = node.vertex();
|
||||||
if (!ueq(inNode.u, curve.uMin)) {
|
if (!ueq(inNode.u, curve.uMin)) {
|
||||||
[,edgeCurve] = edgeCurve.split(vertexA.point);
|
[,edgeCurve] = edgeCurve.split(vertexA.point);
|
||||||
}
|
}
|
||||||
|
|
@ -877,7 +877,7 @@ function split(nodes, curve, result, faceA, faceB) {
|
||||||
|
|
||||||
for (let [edge, nodes] of edgesToSplits) {
|
for (let [edge, nodes] of edgesToSplits) {
|
||||||
nodes.sort(({edgeSplitInfo:{u}}) => u);
|
nodes.sort(({edgeSplitInfo:{u}}) => u);
|
||||||
for (let node of nodes) {
|
for (const node of nodes) {
|
||||||
[,edge] = splitEdgeByVertex(edge, node.vertex());
|
[,edge] = splitEdgeByVertex(edge, node.vertex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -894,7 +894,7 @@ function splitEdgeByVertex(edge, vertex) {
|
||||||
const edge2 = new Edge(curves[1], vertex, edge.halfEdge1.vertexB);
|
const edge2 = new Edge(curves[1], vertex, edge.halfEdge1.vertexB);
|
||||||
|
|
||||||
function updateInLoop(halfEdge, h1, h2) {
|
function updateInLoop(halfEdge, h1, h2) {
|
||||||
let halfEdges = halfEdge.loop.halfEdges;
|
const halfEdges = halfEdge.loop.halfEdges;
|
||||||
halfEdges.splice(halfEdges.indexOf(halfEdge), 1, h1, h2);
|
halfEdges.splice(halfEdges.indexOf(halfEdge), 1, h1, h2);
|
||||||
h1.loop = halfEdge.loop;
|
h1.loop = halfEdge.loop;
|
||||||
h2.loop = halfEdge.loop;
|
h2.loop = halfEdge.loop;
|
||||||
|
|
@ -913,7 +913,7 @@ function splitEdgeByVertex(edge, vertex) {
|
||||||
updateInLoop(edge.halfEdge2, edge2.halfEdge2, edge1.halfEdge2);
|
updateInLoop(edge.halfEdge2, edge2.halfEdge2, edge1.halfEdge2);
|
||||||
|
|
||||||
function transferPriority(from, to) {
|
function transferPriority(from, to) {
|
||||||
let priority = getPriority(from);
|
const priority = getPriority(from);
|
||||||
if (priority !== 0) {
|
if (priority !== 0) {
|
||||||
EdgeSolveData.setPriority(to, priority);
|
EdgeSolveData.setPriority(to, priority);
|
||||||
}
|
}
|
||||||
|
|
@ -946,15 +946,15 @@ export function isInsideEnclose(normal, testee, inVec, outVec, strict){
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let pivot = inVec.negate();
|
const pivot = inVec.negate();
|
||||||
if (strict && veq(pivot, testee)) {
|
if (strict && veq(pivot, testee)) {
|
||||||
//TODO: improve error report
|
//TODO: improve error report
|
||||||
throw new CadError({
|
throw new CadError({
|
||||||
relatedTopoObjects: [testee]
|
relatedTopoObjects: [testee]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let enclosureAngle = leftTurningMeasure(pivot, outVec, normal);
|
const enclosureAngle = leftTurningMeasure(pivot, outVec, normal);
|
||||||
let testeeAngle = leftTurningMeasure(pivot, testee, normal);
|
const testeeAngle = leftTurningMeasure(pivot, testee, normal);
|
||||||
return testeeAngle < enclosureAngle;
|
return testeeAngle < enclosureAngle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -967,25 +967,25 @@ export const ENCLOSE_CLASSIFICATION = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export function isCurveEntersEnclose(curve, a, b) {
|
export function isCurveEntersEnclose(curve, a, b) {
|
||||||
let pt = a.vertexB.point;
|
const pt = a.vertexB.point;
|
||||||
let normal = a.loop.face.surface.normal(pt);
|
const normal = a.loop.face.surface.normal(pt);
|
||||||
|
|
||||||
|
|
||||||
let testee = curve.tangentAtPoint(pt);
|
const testee = curve.tangentAtPoint(pt);
|
||||||
let inVec = a.tangentAtEnd();
|
const inVec = a.tangentAtEnd();
|
||||||
let outVec = b.tangentAtStart();
|
const outVec = b.tangentAtStart();
|
||||||
|
|
||||||
let coiIn = veqNeg(inVec, testee);
|
const coiIn = veqNeg(inVec, testee);
|
||||||
let coiOut = veq(outVec, testee);
|
const coiOut = veq(outVec, testee);
|
||||||
|
|
||||||
if (coiIn && coiOut) {
|
if (coiIn && coiOut) {
|
||||||
return ENCLOSE_CLASSIFICATION.UNDEFINED;
|
return ENCLOSE_CLASSIFICATION.UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
let testeeNeg = testee.negate();
|
const testeeNeg = testee.negate();
|
||||||
|
|
||||||
let coiInNeg = veqNeg(inVec, testeeNeg);
|
const coiInNeg = veqNeg(inVec, testeeNeg);
|
||||||
let coiOutNeg = veq(outVec, testeeNeg);
|
const coiOutNeg = veq(outVec, testeeNeg);
|
||||||
|
|
||||||
if (coiInNeg || coiOutNeg) {
|
if (coiInNeg || coiOutNeg) {
|
||||||
return ENCLOSE_CLASSIFICATION.UNDEFINED;
|
return ENCLOSE_CLASSIFICATION.UNDEFINED;
|
||||||
|
|
@ -993,11 +993,11 @@ export function isCurveEntersEnclose(curve, a, b) {
|
||||||
|
|
||||||
let result = ENCLOSE_CLASSIFICATION.UNDEFINED;
|
let result = ENCLOSE_CLASSIFICATION.UNDEFINED;
|
||||||
if (coiIn || coiOut) {
|
if (coiIn || coiOut) {
|
||||||
let insideEncloseNeg = isInsideEnclose(normal, testeeNeg, inVec, outVec);
|
const insideEncloseNeg = isInsideEnclose(normal, testeeNeg, inVec, outVec);
|
||||||
return insideEncloseNeg ? ENCLOSE_CLASSIFICATION.LEAVES : ENCLOSE_CLASSIFICATION.ENTERS;
|
return insideEncloseNeg ? ENCLOSE_CLASSIFICATION.LEAVES : ENCLOSE_CLASSIFICATION.ENTERS;
|
||||||
} else {
|
} else {
|
||||||
let insideEnclose = isInsideEnclose(normal, testee, inVec, outVec);
|
const insideEnclose = isInsideEnclose(normal, testee, inVec, outVec);
|
||||||
let insideEncloseNeg = isInsideEnclose(normal, testeeNeg, inVec, outVec);
|
const insideEncloseNeg = isInsideEnclose(normal, testeeNeg, inVec, outVec);
|
||||||
if (insideEnclose === insideEncloseNeg) {
|
if (insideEnclose === insideEncloseNeg) {
|
||||||
result = ENCLOSE_CLASSIFICATION.TANGENTS;
|
result = ENCLOSE_CLASSIFICATION.TANGENTS;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1078,7 +1078,7 @@ function markEdgeTransferred(edge) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function isEdgeTransferred(edge) {
|
function isEdgeTransferred(edge) {
|
||||||
let data = edge.data[MY];
|
const data = edge.data[MY];
|
||||||
return data && data.transfered;
|
return data && data.transfered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1112,13 +1112,13 @@ class VertexFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
addVertices(vertices) {
|
addVertices(vertices) {
|
||||||
for (let v of vertices) {
|
for (const v of vertices) {
|
||||||
this.vertices.push(v);
|
this.vertices.push(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
find(point) {
|
find(point) {
|
||||||
for (let vertex of this.vertices) {
|
for (const vertex of this.vertices) {
|
||||||
if (veq(point, vertex.point)) {
|
if (veq(point, vertex.point)) {
|
||||||
return vertex;
|
return vertex;
|
||||||
}
|
}
|
||||||
|
|
@ -1168,10 +1168,10 @@ class FaceOperationData extends EdgeGraph {
|
||||||
|
|
||||||
initGraph() {
|
initGraph() {
|
||||||
this.vertexToEdge.clear();
|
this.vertexToEdge.clear();
|
||||||
for (let he of this.face.edges) {
|
for (const he of this.face.edges) {
|
||||||
this.addToGraph(he);
|
this.addToGraph(he);
|
||||||
}
|
}
|
||||||
for (let he of this.newEdges) {
|
for (const he of this.newEdges) {
|
||||||
this.addToGraph(he);
|
this.addToGraph(he);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1187,7 +1187,7 @@ class FaceOperationData extends EdgeGraph {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let opp = this.findOppositeEdge(he);
|
const opp = this.findOppositeEdge(he);
|
||||||
if (opp) {
|
if (opp) {
|
||||||
this.collidedEdges.push(opp, he);
|
this.collidedEdges.push(opp, he);
|
||||||
}
|
}
|
||||||
|
|
@ -1197,7 +1197,7 @@ class FaceOperationData extends EdgeGraph {
|
||||||
list = [];
|
list = [];
|
||||||
this.vertexToEdge.set(he.vertexA, list);
|
this.vertexToEdge.set(he.vertexA, list);
|
||||||
} else {
|
} else {
|
||||||
for (let ex of list) {
|
for (const ex of list) {
|
||||||
if (he.vertexB === ex.vertexB && isSameEdge(he, ex)) {
|
if (he.vertexB === ex.vertexB && isSameEdge(he, ex)) {
|
||||||
this.collidedEdges.push(ex, he);
|
this.collidedEdges.push(ex, he);
|
||||||
// ex.attachManifold(he);
|
// ex.attachManifold(he);
|
||||||
|
|
@ -1210,9 +1210,9 @@ class FaceOperationData extends EdgeGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
findOppositeEdge(e1) {
|
findOppositeEdge(e1) {
|
||||||
let others = this.vertexToEdge.get(e1.vertexB);
|
const others = this.vertexToEdge.get(e1.vertexB);
|
||||||
if (others) {
|
if (others) {
|
||||||
for (let e2 of others) {
|
for (const e2 of others) {
|
||||||
if (e1.vertexA === e2.vertexB && isSameEdge(e1, e2)) {
|
if (e1.vertexA === e2.vertexB && isSameEdge(e1, e2)) {
|
||||||
return e2;
|
return e2;
|
||||||
}
|
}
|
||||||
|
|
@ -1223,7 +1223,7 @@ class FaceOperationData extends EdgeGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeFromListInMap(map, key, value) {
|
function removeFromListInMap(map, key, value) {
|
||||||
let list = map.get(key);
|
const list = map.get(key);
|
||||||
if (list) {
|
if (list) {
|
||||||
const idx = list.indexOf(value);
|
const idx = list.indexOf(value);
|
||||||
if (idx !== -1) {
|
if (idx !== -1) {
|
||||||
|
|
@ -1233,17 +1233,17 @@ function removeFromListInMap(map, key, value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function edgesHaveSameEnds(e1, e2) {
|
function edgesHaveSameEnds(e1, e2) {
|
||||||
let a1 = e1.vertexA;
|
const a1 = e1.vertexA;
|
||||||
let b1 = e1.vertexB;
|
const b1 = e1.vertexB;
|
||||||
let a2 = e2.vertexA;
|
const a2 = e2.vertexA;
|
||||||
let b2 = e2.vertexB;
|
const b2 = e2.vertexB;
|
||||||
return (a1 === a2 && b1 === b2) || (a1 === b2 && b1 === a2)
|
return (a1 === a2 && b1 === b2) || (a1 === b2 && b1 === a2)
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSameEdge(e1, e2) {
|
function isSameEdge(e1, e2) {
|
||||||
let tess = e1.tessellate();
|
const tess = e1.tessellate();
|
||||||
for (let pt1 of tess) {
|
for (const pt1 of tess) {
|
||||||
let pt2 = e2.edge.curve.point(e2.edge.curve.param(pt1));
|
const pt2 = e2.edge.curve.point(e2.edge.curve.param(pt1));
|
||||||
if (!veq(pt1, pt2)) {
|
if (!veq(pt1, pt2)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -1252,12 +1252,12 @@ function isSameEdge(e1, e2) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function curveAndEdgeCoincident(curve, edge) {
|
function curveAndEdgeCoincident(curve, edge) {
|
||||||
let tess = edge.tessellate();
|
const tess = edge.tessellate();
|
||||||
//Do reverse to optimize a bit because the first point is usually checked
|
//Do reverse to optimize a bit because the first point is usually checked
|
||||||
let touches = 0;
|
let touches = 0;
|
||||||
for (let i = tess.length - 1; i >= 0; i--) {
|
for (let i = tess.length - 1; i >= 0; i--) {
|
||||||
let pt1 = tess[i];
|
const pt1 = tess[i];
|
||||||
let pt2 = curve.point(curve.param(pt1));
|
const pt2 = curve.point(curve.param(pt1));
|
||||||
if (!veq(pt1, pt2)) {
|
if (!veq(pt1, pt2)) {
|
||||||
if (touches > 1) {
|
if (touches > 1) {
|
||||||
//partial tangency should be handled before face-face intersection analysis
|
//partial tangency should be handled before face-face intersection analysis
|
||||||
|
|
@ -1275,11 +1275,11 @@ function curveAndEdgeCoincident(curve, edge) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function edgeCollinearToFace(edge, face) {
|
function edgeCollinearToFace(edge, face) {
|
||||||
let tess = edge.tessellate();
|
const tess = edge.tessellate();
|
||||||
for (let i = 0; i < tess.length; ++i) {
|
for (let i = 0; i < tess.length; ++i) {
|
||||||
let pt1 = tess[i];
|
const pt1 = tess[i];
|
||||||
let [u, v] = face.surface.param(pt1);
|
const [u, v] = face.surface.param(pt1);
|
||||||
let pt2 = face.surface.point(u, v);
|
const pt2 = face.surface.point(u, v);
|
||||||
if (!veq(pt1, pt2)) {
|
if (!veq(pt1, pt2)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -1289,9 +1289,9 @@ function edgeCollinearToFace(edge, face) {
|
||||||
|
|
||||||
function checkFaceDataForError(workingFaces) {
|
function checkFaceDataForError(workingFaces) {
|
||||||
if (workingFaces.find(f => f.op.collidedEdges.length !== 0)) {
|
if (workingFaces.find(f => f.op.collidedEdges.length !== 0)) {
|
||||||
let relatedTopoObjects = [];
|
const relatedTopoObjects = [];
|
||||||
for (let face of workingFaces) {
|
for (const face of workingFaces) {
|
||||||
for (let err of face.op.collidedEdges) {
|
for (const err of face.op.collidedEdges) {
|
||||||
relatedTopoObjects.push(err);
|
relatedTopoObjects.push(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ export function createPrism(basePoints, height) {
|
||||||
const lidPath = [];
|
const lidPath = [];
|
||||||
|
|
||||||
for (let i = 0; i < basePoints.length; i++) {
|
for (let i = 0; i < basePoints.length; i++) {
|
||||||
let j = (i + 1) % basePoints.length;
|
const j = (i + 1) % basePoints.length;
|
||||||
basePath.push(BrepCurve.createLinearCurve(basePoints[i], basePoints[j]));
|
basePath.push(BrepCurve.createLinearCurve(basePoints[i], basePoints[j]));
|
||||||
lidPath.push(BrepCurve.createLinearCurve(lidPoints[i], lidPoints[j]));
|
lidPath.push(BrepCurve.createLinearCurve(lidPoints[i], lidPoints[j]));
|
||||||
}
|
}
|
||||||
|
|
@ -71,24 +71,24 @@ function assemble(walls, basePlane, lidPlane) {
|
||||||
const baseEdges = [];
|
const baseEdges = [];
|
||||||
const lidEdges = [];
|
const lidEdges = [];
|
||||||
|
|
||||||
for (let w of walls) {
|
for (const w of walls) {
|
||||||
let wallEdge = Edge.fromCurve(w.isoCurveAlignV(0));
|
const wallEdge = Edge.fromCurve(w.isoCurveAlignV(0));
|
||||||
wallEdges.push(wallEdge);
|
wallEdges.push(wallEdge);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < wallEdges.length; ++i) {
|
for (let i = 0; i < wallEdges.length; ++i) {
|
||||||
let j = (i + 1) % wallEdges.length;
|
const j = (i + 1) % wallEdges.length;
|
||||||
let curr = wallEdges[i];
|
const curr = wallEdges[i];
|
||||||
let next = wallEdges[j];
|
const next = wallEdges[j];
|
||||||
let wall = walls[i];
|
const wall = walls[i];
|
||||||
|
|
||||||
let baseEdge = new Edge(wall.isoCurveAlignU(1), curr.halfEdge1.vertexB, next.halfEdge1.vertexB);
|
const baseEdge = new Edge(wall.isoCurveAlignU(1), curr.halfEdge1.vertexB, next.halfEdge1.vertexB);
|
||||||
let lidEdge = new Edge(wall.isoCurveAlignU(0), curr.halfEdge1.vertexA, next.halfEdge1.vertexA);
|
const lidEdge = new Edge(wall.isoCurveAlignU(0), curr.halfEdge1.vertexA, next.halfEdge1.vertexA);
|
||||||
|
|
||||||
baseEdges.push(baseEdge);
|
baseEdges.push(baseEdge);
|
||||||
lidEdges.push(lidEdge);
|
lidEdges.push(lidEdge);
|
||||||
|
|
||||||
let wallFace = new Face(wall);
|
const wallFace = new Face(wall);
|
||||||
wallFace.outerLoop.halfEdges.push(baseEdge.halfEdge2, curr.halfEdge2, lidEdge.halfEdge1, next.halfEdge1);
|
wallFace.outerLoop.halfEdges.push(baseEdge.halfEdge2, curr.halfEdge2, lidEdge.halfEdge1, next.halfEdge1);
|
||||||
wallFace.outerLoop.link();
|
wallFace.outerLoop.link();
|
||||||
shell.faces.push(wallFace);
|
shell.faces.push(wallFace);
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import PIP from '../../../web/app/cad/tess/pip';
|
||||||
import {isCCW} from "geom/euclidean";
|
import {isCCW} from "geom/euclidean";
|
||||||
|
|
||||||
export function evolveFace(originFace, loops) {
|
export function evolveFace(originFace, loops) {
|
||||||
let out = [];
|
const out = [];
|
||||||
const originSurface = originFace.surface;
|
const originSurface = originFace.surface;
|
||||||
let invertedSurface = null;
|
let invertedSurface = null;
|
||||||
function invertSurface() {
|
function invertSurface() {
|
||||||
|
|
@ -32,7 +32,7 @@ export function evolveFace(originFace, loops) {
|
||||||
loop.face = newFace;
|
loop.face = newFace;
|
||||||
out.push(newFace);
|
out.push(newFace);
|
||||||
|
|
||||||
for (let child of nestedLoop.nesting) {
|
for (const child of nestedLoop.nesting) {
|
||||||
if (child.level == level + 2) {
|
if (child.level == level + 2) {
|
||||||
createFaces(child, level + 2);
|
createFaces(child, level + 2);
|
||||||
} else if (child.level == level + 1) {
|
} else if (child.level == level + 1) {
|
||||||
|
|
@ -46,7 +46,7 @@ export function evolveFace(originFace, loops) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const nestedLoops = getNestedLoops(originFace, loops);
|
const nestedLoops = getNestedLoops(originFace, loops);
|
||||||
for (let nestedLoop of nestedLoops) {
|
for (const nestedLoop of nestedLoops) {
|
||||||
if (nestedLoop.level == 0) {
|
if (nestedLoop.level == 0) {
|
||||||
createFaces(nestedLoop, 0);
|
createFaces(nestedLoop, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +69,7 @@ function getNestedLoops(face, brepLoops) {
|
||||||
|
|
||||||
const loops = brepLoops.map(loop => new NestedLoop(loop));
|
const loops = brepLoops.map(loop => new NestedLoop(loop));
|
||||||
function contains(loop, other) {
|
function contains(loop, other) {
|
||||||
for (let point of other.workingPolygon) {
|
for (const point of other.workingPolygon) {
|
||||||
if (!loop.pip(point).inside) {
|
if (!loop.pip(point).inside) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,19 +47,19 @@ export class StitchedCurve {
|
||||||
|
|
||||||
export function update(shell) {
|
export function update(shell) {
|
||||||
const index = new DoubleKeyMap();
|
const index = new DoubleKeyMap();
|
||||||
for (let face of shell.faces) {
|
for (const face of shell.faces) {
|
||||||
const stitchedSurface = face.data[FACE_CHUNK];
|
const stitchedSurface = face.data[FACE_CHUNK];
|
||||||
if (stitchedSurface) {
|
if (stitchedSurface) {
|
||||||
stitchedSurface.clear();
|
stitchedSurface.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let face of shell.faces) {
|
for (const face of shell.faces) {
|
||||||
const stitchedSurface = face.data[FACE_CHUNK];
|
const stitchedSurface = face.data[FACE_CHUNK];
|
||||||
if (stitchedSurface) {
|
if (stitchedSurface) {
|
||||||
stitchedSurface.addFace(face);
|
stitchedSurface.addFace(face);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let e of shell.edges) {
|
for (const e of shell.edges) {
|
||||||
const face1 = e.halfEdge1.loop.face;
|
const face1 = e.halfEdge1.loop.face;
|
||||||
const face2 = e.halfEdge2.loop.face;
|
const face2 = e.halfEdge2.loop.face;
|
||||||
const stitchedSurface1 = face1.data[FACE_CHUNK];
|
const stitchedSurface1 = face1.data[FACE_CHUNK];
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ export default function pickPointInside2dPolygon(polygon) {
|
||||||
tr.points[tr.counter] = data;
|
tr.points[tr.counter] = data;
|
||||||
tr.counter ++;
|
tr.counter ++;
|
||||||
if (tr.counter === 3) {
|
if (tr.counter === 3) {
|
||||||
let trArea = Math.abs(area(tr.points));
|
const trArea = Math.abs(area(tr.points));
|
||||||
if (trArea > tr.bestArea) {
|
if (trArea > tr.bestArea) {
|
||||||
tr.bestArea = trArea;
|
tr.bestArea = trArea;
|
||||||
tr.bestTr = Array.from(tr.points);
|
tr.bestTr = Array.from(tr.points);
|
||||||
|
|
@ -26,9 +26,9 @@ export default function pickPointInside2dPolygon(polygon) {
|
||||||
};
|
};
|
||||||
tessy.gluTessBeginPolygon(tracker);
|
tessy.gluTessBeginPolygon(tracker);
|
||||||
|
|
||||||
for (let path of polygon) {
|
for (const path of polygon) {
|
||||||
tessy.gluTessBeginContour();
|
tessy.gluTessBeginContour();
|
||||||
for (let p of path) {
|
for (const p of path) {
|
||||||
tessy.gluTessVertex([p.x, p.y, 0], p);
|
tessy.gluTessVertex([p.x, p.y, 0], p);
|
||||||
}
|
}
|
||||||
tessy.gluTessEndContour();
|
tessy.gluTessEndContour();
|
||||||
|
|
@ -39,7 +39,7 @@ export default function pickPointInside2dPolygon(polygon) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let center = tracker.bestTr[0].copy();
|
const center = tracker.bestTr[0].copy();
|
||||||
center._plus(tracker.bestTr[1]);
|
center._plus(tracker.bestTr[1]);
|
||||||
center._plus(tracker.bestTr[2]);
|
center._plus(tracker.bestTr[2]);
|
||||||
center._divide(3);
|
center._divide(3);
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
export default function pertrub([x, y, z]) {
|
export default function pertrub([x, y, z]) {
|
||||||
|
|
||||||
let s = x + y + z;
|
const s = x + y + z;
|
||||||
x = pertrubFloat(x + 3 + s);
|
x = pertrubFloat(x + 3 + s);
|
||||||
y = pertrubFloat(y + 5 + s);
|
y = pertrubFloat(y + 5 + s);
|
||||||
z = pertrubFloat(z + 7 + s);
|
z = pertrubFloat(z + 7 + s);
|
||||||
|
|
||||||
let r = Math.sqrt(x*x + y*y + z*z);
|
const r = Math.sqrt(x*x + y*y + z*z);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
x/r,
|
x/r,
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ export default class Bus {
|
||||||
tokens = [tokens];
|
tokens = [tokens];
|
||||||
}
|
}
|
||||||
|
|
||||||
let connection = () => {
|
const connection = () => {
|
||||||
callback(this.tokensToStates(tokens));
|
callback(this.tokensToStates(tokens));
|
||||||
};
|
};
|
||||||
tokens.forEach(token => {
|
tokens.forEach(token => {
|
||||||
|
|
@ -57,7 +57,7 @@ export default class Bus {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStates(tokens, updater) {
|
updateStates(tokens, updater) {
|
||||||
let updated = updater(this.tokensToStates(tokens));
|
const updated = updater(this.tokensToStates(tokens));
|
||||||
for (let i = 0; i < tokens.length; ++i) {
|
for (let i = 0; i < tokens.length; ++i) {
|
||||||
this.dispatch(tokens[i], updated[i]);
|
this.dispatch(tokens[i], updated[i]);
|
||||||
}
|
}
|
||||||
|
|
@ -90,7 +90,7 @@ export default class Bus {
|
||||||
}
|
}
|
||||||
this.lock.add(key);
|
this.lock.add(key);
|
||||||
try {
|
try {
|
||||||
let listenerList = this.listeners[key];
|
const listenerList = this.listeners[key];
|
||||||
if (listenerList !== undefined) {
|
if (listenerList !== undefined) {
|
||||||
for (let i = 0; i < listenerList.length; i++) {
|
for (let i = 0; i < listenerList.length; i++) {
|
||||||
const callback = listenerList[i];
|
const callback = listenerList[i];
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
|
|
||||||
export function toCString(str) {
|
export function toCString(str) {
|
||||||
let buffer = Module._malloc(str.length + 1);
|
const buffer = Module._malloc(str.length + 1);
|
||||||
writeAsciiToMemory(str, buffer);
|
writeAsciiToMemory(str, buffer);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function callEngine(request, engineFunc) {
|
export function callEngine(request, engineFunc) {
|
||||||
let toCStringRequest = toCString(JSON.stringify(request));
|
const toCStringRequest = toCString(JSON.stringify(request));
|
||||||
engineFunc(toCStringRequest);
|
engineFunc(toCStringRequest);
|
||||||
Module._free(toCStringRequest);
|
Module._free(toCStringRequest);
|
||||||
return __E0_ENGINE_EXCHANGE_VAL;
|
return __E0_ENGINE_EXCHANGE_VAL;
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ export default function camelCaseSplit(str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function camelCaseSplitToStr(str) {
|
export function camelCaseSplitToStr(str) {
|
||||||
let words = camelCaseSplit(str);
|
const words = camelCaseSplit(str);
|
||||||
if (words.length !== 0) {
|
if (words.length !== 0) {
|
||||||
return words.map(w => w.toLowerCase()).join(' ');
|
return words.map(w => w.toLowerCase()).join(' ');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ export default class Joints {
|
||||||
}
|
}
|
||||||
|
|
||||||
connected(a, b) {
|
connected(a, b) {
|
||||||
let set = this.map.get(a);
|
const set = this.map.get(a);
|
||||||
if (!set) {
|
if (!set) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -31,7 +31,7 @@ export default class Joints {
|
||||||
}
|
}
|
||||||
|
|
||||||
master(node) {
|
master(node) {
|
||||||
let tuple = this.map.get(node);
|
const tuple = this.map.get(node);
|
||||||
if (!tuple) {
|
if (!tuple) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ export class OrderedMap {
|
||||||
|
|
||||||
delete(key) {
|
delete(key) {
|
||||||
this.map.delete(key);
|
this.map.delete(key);
|
||||||
let index = this.order.indexOf(key);
|
const index = this.order.indexOf(key);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
this.order.splice(index, 1);
|
this.order.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,16 @@ export default function shallowEqual(objA, objB) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let aKeys = Object.keys(objA);
|
const aKeys = Object.keys(objA);
|
||||||
let bKeys = Object.keys(objB);
|
const bKeys = Object.keys(objB);
|
||||||
let len = aKeys.length;
|
const len = aKeys.length;
|
||||||
|
|
||||||
if (bKeys.length !== len) {
|
if (bKeys.length !== len) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < len; i++) {
|
for (let i = 0; i < len; i++) {
|
||||||
let key = aKeys[i];
|
const key = aKeys[i];
|
||||||
|
|
||||||
if (objA[key] !== objB[key]) {
|
if (objA[key] !== objB[key]) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -3,22 +3,22 @@ import newtonIterations, {newtonIterationsOnInterval} from './newtonIterations';
|
||||||
import {curveTessParams} from '../impl/curve/curve-tess';
|
import {curveTessParams} from '../impl/curve/curve-tess';
|
||||||
|
|
||||||
export function closestToCurveParam(curve, pt) {
|
export function closestToCurveParam(curve, pt) {
|
||||||
let [intMin, intMax] = findClosestToCurveInterval(curve, pt)
|
const [intMin, intMax] = findClosestToCurveInterval(curve, pt)
|
||||||
return solveClosestToCurveParamExactly(curve, pt, intMin, intMax)
|
return solveClosestToCurveParamExactly(curve, pt, intMin, intMax)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function findClosestToCurveInterval(curve, pt) {
|
export function findClosestToCurveInterval(curve, pt) {
|
||||||
let [uMin, uMax] = curve.domain();
|
const [uMin, uMax] = curve.domain();
|
||||||
let chunks = curveTessParams(curve, uMin, uMax, 10);
|
const chunks = curveTessParams(curve, uMin, uMax, 10);
|
||||||
let heroDist = -1;
|
let heroDist = -1;
|
||||||
let hero = -1;
|
let hero = -1;
|
||||||
for (let i = 1; i < chunks.length; ++i) {
|
for (let i = 1; i < chunks.length; ++i) {
|
||||||
let startParam = chunks[i - 1];
|
const startParam = chunks[i - 1];
|
||||||
let endParam = chunks[i];
|
const endParam = chunks[i];
|
||||||
let a = curve.point(startParam);
|
const a = curve.point(startParam);
|
||||||
let b = curve.point(endParam);
|
const b = curve.point(endParam);
|
||||||
|
|
||||||
let dist = distanceSqToSegment(a, b, pt);
|
const dist = distanceSqToSegment(a, b, pt);
|
||||||
if (hero === -1 || dist < heroDist) {
|
if (hero === -1 || dist < heroDist) {
|
||||||
heroDist = dist;
|
heroDist = dist;
|
||||||
hero = i;
|
hero = i;
|
||||||
|
|
@ -28,17 +28,17 @@ export function findClosestToCurveInterval(curve, pt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function distanceSqToSegment(a, b, pt) {
|
function distanceSqToSegment(a, b, pt) {
|
||||||
let ab = vec.sub(b, a);
|
const ab = vec.sub(b, a);
|
||||||
let test = vec.sub(pt, a);
|
const test = vec.sub(pt, a);
|
||||||
let abLength = vec.length(ab);
|
const abLength = vec.length(ab);
|
||||||
let abUnit = vec._div(ab, abLength);
|
const abUnit = vec._div(ab, abLength);
|
||||||
let proj = vec.dot(abUnit, test);
|
const proj = vec.dot(abUnit, test);
|
||||||
if (proj <= 0) {
|
if (proj <= 0) {
|
||||||
return vec.distanceSq(a, pt);
|
return vec.distanceSq(a, pt);
|
||||||
} else if (proj >= abLength) {
|
} else if (proj >= abLength) {
|
||||||
return vec.distanceSq(b, pt);
|
return vec.distanceSq(b, pt);
|
||||||
} else {
|
} else {
|
||||||
let projV = vec._mul(abUnit, proj);
|
const projV = vec._mul(abUnit, proj);
|
||||||
return vec.distanceSq(test, projV)
|
return vec.distanceSq(test, projV)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -56,13 +56,13 @@ export function solveClosestToCurveParamExactly(curve, pt, intMin, intMax, tol)
|
||||||
const X=0, Y=1, Z=2;
|
const X=0, Y=1, Z=2;
|
||||||
function squareDistanceFn(u) {
|
function squareDistanceFn(u) {
|
||||||
|
|
||||||
let [f, d1, d2] = curve.eval(u, 2);
|
const [f, d1, d2] = curve.eval(u, 2);
|
||||||
|
|
||||||
let r1Comp = i => 2 * f[i] * d1[i] - 2 * pt[i] * d1[i];
|
const r1Comp = i => 2 * f[i] * d1[i] - 2 * pt[i] * d1[i];
|
||||||
let r2Comp = i => 2 * f[i] * d2[i] + 2 * d1[i] * d1[i] - 2 * pt[i] * d2[i];
|
const r2Comp = i => 2 * f[i] * d2[i] + 2 * d1[i] * d1[i] - 2 * pt[i] * d2[i];
|
||||||
|
|
||||||
let r1 = r1Comp(X) + r1Comp(Y) + r1Comp(Z);
|
const r1 = r1Comp(X) + r1Comp(Y) + r1Comp(Z);
|
||||||
let r2 = r2Comp(X) + r2Comp(Y) + r2Comp(Z);
|
const r2 = r2Comp(X) + r2Comp(Y) + r2Comp(Z);
|
||||||
|
|
||||||
return [r1, r2];
|
return [r1, r2];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,17 +4,17 @@ import {closestToCurveParam} from './closestPoint';
|
||||||
import InvertedCurve from './invertedCurve';
|
import InvertedCurve from './invertedCurve';
|
||||||
|
|
||||||
export default function CubicHermiteInterpolation(points, tangents) {
|
export default function CubicHermiteInterpolation(points, tangents) {
|
||||||
let n = points.length;
|
const n = points.length;
|
||||||
let knots = new Array(n).fill().map((e,i) => i);
|
const knots = new Array(n).fill().map((e,i) => i);
|
||||||
let beziers = [];
|
const beziers = [];
|
||||||
for (let i = 1; i < n; i++) {
|
for (let i = 1; i < n; i++) {
|
||||||
let p0 = points[i - 1];
|
const p0 = points[i - 1];
|
||||||
let p3 = points[i];
|
const p3 = points[i];
|
||||||
let tangent1 = tangents[i - 1];
|
const tangent1 = tangents[i - 1];
|
||||||
let tangent2 = tangents[i];
|
const tangent2 = tangents[i];
|
||||||
let length = vec.length(vec.sub(p3, p0)) * 0.5;
|
const length = vec.length(vec.sub(p3, p0)) * 0.5;
|
||||||
let p1 = vec.add(p0, vec.mul(tangent1, length));
|
const p1 = vec.add(p0, vec.mul(tangent1, length));
|
||||||
let p2 = vec.sub(p3, vec.mul(tangent2, length));
|
const p2 = vec.sub(p3, vec.mul(tangent2, length));
|
||||||
beziers.push({p0, p1, p2, p3});
|
beziers.push({p0, p1, p2, p3});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,9 +43,9 @@ export default function CubicHermiteInterpolation(points, tangents) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function evaluate(u, num) {
|
function evaluate(u, num) {
|
||||||
let [pieceIndex, uL] = localizeParam(u);
|
const [pieceIndex, uL] = localizeParam(u);
|
||||||
let {p0, p1, p2, p3} = beziers[pieceIndex];
|
const {p0, p1, p2, p3} = beziers[pieceIndex];
|
||||||
let out = [];
|
const out = [];
|
||||||
for (let i = 0; i <= num; ++i) {
|
for (let i = 0; i <= num; ++i) {
|
||||||
out.push(evalPatch(p0, p1, p2, p3, uL, i));
|
out.push(evalPatch(p0, p1, p2, p3, uL, i));
|
||||||
}
|
}
|
||||||
|
|
@ -53,8 +53,8 @@ export default function CubicHermiteInterpolation(points, tangents) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function point(u) {
|
function point(u) {
|
||||||
let [pieceIndex, uL] = localizeParam(u);
|
const [pieceIndex, uL] = localizeParam(u);
|
||||||
let {p0, p1, p2, p3} = beziers[pieceIndex];
|
const {p0, p1, p2, p3} = beziers[pieceIndex];
|
||||||
return cubicBezierPoint(p0, p1, p2, p3, uL);
|
return cubicBezierPoint(p0, p1, p2, p3, uL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,21 +2,21 @@ import * as vec from 'math/vec';
|
||||||
import {perpendicularVector} from "../euclidean";
|
import {perpendicularVector} from "../euclidean";
|
||||||
|
|
||||||
export function frenetFrame(D1, D2) {
|
export function frenetFrame(D1, D2) {
|
||||||
let T = vec.normalize(D1);
|
const T = vec.normalize(D1);
|
||||||
let N = vec.normalize(D2);
|
const N = vec.normalize(D2);
|
||||||
let B = vec.cross(T, N);
|
const B = vec.cross(T, N);
|
||||||
return [T, N, B];
|
return [T, N, B];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pseudoFrenetFrame(D1) {
|
export function pseudoFrenetFrame(D1) {
|
||||||
let T = vec.normalize(D1);
|
const T = vec.normalize(D1);
|
||||||
let N = perpendicularVector(T);
|
const N = perpendicularVector(T);
|
||||||
let B = vec.cross(T, N);
|
const B = vec.cross(T, N);
|
||||||
return [T, N, B];
|
return [T, N, B];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function advancePseudoFrenetFrame(refFrame, T) {
|
export function advancePseudoFrenetFrame(refFrame, T) {
|
||||||
let B = vec._normalize(vec.cross(T, refFrame[1]));
|
const B = vec._normalize(vec.cross(T, refFrame[1]));
|
||||||
let N = vec.cross(B, T);
|
const N = vec.cross(B, T);
|
||||||
return [T, N, B];
|
return [T, N, B];
|
||||||
}
|
}
|
||||||
|
|
@ -12,12 +12,12 @@ export class IntersectionCurve {
|
||||||
|
|
||||||
fixDirection(exactPoints, surfaceA, surfaceB);
|
fixDirection(exactPoints, surfaceA, surfaceB);
|
||||||
|
|
||||||
let tangents = [];
|
const tangents = [];
|
||||||
for (let i = 0; i < exactPoints.length; i++) {
|
for (let i = 0; i < exactPoints.length; i++) {
|
||||||
let pt = exactPoints[i];
|
const pt = exactPoints[i];
|
||||||
let auxInverse = i === exactPoints.length - 1;
|
const auxInverse = i === exactPoints.length - 1;
|
||||||
let auxPt = auxInverse ? exactPoints[i - 1] : exactPoints[i + 1];
|
const auxPt = auxInverse ? exactPoints[i - 1] : exactPoints[i + 1];
|
||||||
let tangent = curveSSTangent(pt, surfaceA, surfaceB, auxPt, auxInverse);
|
const tangent = curveSSTangent(pt, surfaceA, surfaceB, auxPt, auxInverse);
|
||||||
tangents.push(tangent);
|
tangents.push(tangent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -26,8 +26,8 @@ export class IntersectionCurve {
|
||||||
this.approx = new CubicHermiteInterpolation(exactPoints, tangents);
|
this.approx = new CubicHermiteInterpolation(exactPoints, tangents);
|
||||||
|
|
||||||
this.exactify = (pt) => {
|
this.exactify = (pt) => {
|
||||||
let uvA = surfaceClosestParam(surfaceA, pt);
|
const uvA = surfaceClosestParam(surfaceA, pt);
|
||||||
let uvB = surfaceClosestParam(surfaceB, pt);
|
const uvB = surfaceClosestParam(surfaceB, pt);
|
||||||
return verb.eval.Intersect.surfacesAtPointWithEstimate(surfaceA,surfaceB,uvA,uvB,TOLERANCE).point;
|
return verb.eval.Intersect.surfacesAtPointWithEstimate(surfaceA,surfaceB,uvA,uvB,TOLERANCE).point;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -42,13 +42,13 @@ export class IntersectionCurve {
|
||||||
}
|
}
|
||||||
|
|
||||||
eval(u, num) {
|
eval(u, num) {
|
||||||
let pt = this.point(u);
|
const pt = this.point(u);
|
||||||
|
|
||||||
// let [uA, vA] = surfaceClosestParam(this.surfaceA, pt);
|
// let [uA, vA] = surfaceClosestParam(this.surfaceA, pt);
|
||||||
// let [uB, vB] = surfaceClosestParam(this.surfaceB, pt);
|
// let [uB, vB] = surfaceClosestParam(this.surfaceB, pt);
|
||||||
|
|
||||||
let out = [];
|
const out = [];
|
||||||
let approxEval = this.approx.eval(u, num);
|
const approxEval = this.approx.eval(u, num);
|
||||||
for (let i = 0; i < num + 1; ++i) {
|
for (let i = 0; i < num + 1; ++i) {
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
out.push(pt);
|
out.push(pt);
|
||||||
|
|
@ -64,7 +64,7 @@ export class IntersectionCurve {
|
||||||
}
|
}
|
||||||
|
|
||||||
point(u) {
|
point(u) {
|
||||||
let pt = this.approx.point(u);
|
const pt = this.approx.point(u);
|
||||||
return this.exactify(pt);
|
return this.exactify(pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,23 +102,23 @@ export class IntersectionCurve {
|
||||||
}
|
}
|
||||||
|
|
||||||
function curveSSTangent(pt, surfaceA, surfaceB, auxPt, auxInverse) {
|
function curveSSTangent(pt, surfaceA, surfaceB, auxPt, auxInverse) {
|
||||||
let [uA, vA] = surfaceClosestParam(surfaceA, pt);
|
const [uA, vA] = surfaceClosestParam(surfaceA, pt);
|
||||||
let [uB, vB] = surfaceClosestParam(surfaceB, pt);
|
const [uB, vB] = surfaceClosestParam(surfaceB, pt);
|
||||||
|
|
||||||
let dA = verb.eval.Eval.rationalSurfaceDerivatives(surfaceA, uA, vA, 1);
|
const dA = verb.eval.Eval.rationalSurfaceDerivatives(surfaceA, uA, vA, 1);
|
||||||
let dB = verb.eval.Eval.rationalSurfaceDerivatives(surfaceB, uB, vB, 1);
|
const dB = verb.eval.Eval.rationalSurfaceDerivatives(surfaceB, uB, vB, 1);
|
||||||
|
|
||||||
let nA = vec.normalize(vec.cross(dA[1][0], dA[0][1]));
|
const nA = vec.normalize(vec.cross(dA[1][0], dA[0][1]));
|
||||||
let nB = vec.normalize(vec.cross(dB[1][0], dB[0][1]));
|
const nB = vec.normalize(vec.cross(dB[1][0], dB[0][1]));
|
||||||
|
|
||||||
if (veq3(nA, nB)) {
|
if (veq3(nA, nB)) {
|
||||||
let segV = vec.sub(auxPt, pt);
|
const segV = vec.sub(auxPt, pt);
|
||||||
let dV = vec.mul(nA, - vec.dot(nA, segV));
|
const dV = vec.mul(nA, - vec.dot(nA, segV));
|
||||||
let projectionOntoTangentPlane = vec._add(dV, auxPt);
|
const projectionOntoTangentPlane = vec._add(dV, auxPt);
|
||||||
if (auxInverse) {
|
if (auxInverse) {
|
||||||
vec._negate(projectionOntoTangentPlane);
|
vec._negate(projectionOntoTangentPlane);
|
||||||
}
|
}
|
||||||
let estimatedTangent = vec._normalize(vec._sub(projectionOntoTangentPlane, pt));
|
const estimatedTangent = vec._normalize(vec._sub(projectionOntoTangentPlane, pt));
|
||||||
return estimatedTangent;
|
return estimatedTangent;
|
||||||
} else {
|
} else {
|
||||||
return vec._normalize(vec.cross(nA, nB));
|
return vec._normalize(vec.cross(nA, nB));
|
||||||
|
|
@ -127,29 +127,29 @@ function curveSSTangent(pt, surfaceA, surfaceB, auxPt, auxInverse) {
|
||||||
|
|
||||||
function fixDirection(points, surfaceA, surfaceB) {
|
function fixDirection(points, surfaceA, surfaceB) {
|
||||||
for (let i = 0; i < points.length; i++) {
|
for (let i = 0; i < points.length; i++) {
|
||||||
let pt = points[i];
|
const pt = points[i];
|
||||||
|
|
||||||
let [uA, vA] = surfaceClosestParam(surfaceA, pt);
|
const [uA, vA] = surfaceClosestParam(surfaceA, pt);
|
||||||
let [uB, vB] = surfaceClosestParam(surfaceB, pt);
|
const [uB, vB] = surfaceClosestParam(surfaceB, pt);
|
||||||
|
|
||||||
let dA = verb.eval.Eval.rationalSurfaceDerivatives(surfaceA, uA, vA, 1);
|
const dA = verb.eval.Eval.rationalSurfaceDerivatives(surfaceA, uA, vA, 1);
|
||||||
let dB = verb.eval.Eval.rationalSurfaceDerivatives(surfaceB, uB, vB, 1);
|
const dB = verb.eval.Eval.rationalSurfaceDerivatives(surfaceB, uB, vB, 1);
|
||||||
|
|
||||||
let nA = vec.normalize(vec.cross(dA[1][0], dA[0][1]));
|
const nA = vec.normalize(vec.cross(dA[1][0], dA[0][1]));
|
||||||
let nB = vec.normalize(vec.cross(dB[1][0], dB[0][1]));
|
const nB = vec.normalize(vec.cross(dB[1][0], dB[0][1]));
|
||||||
|
|
||||||
if (!veq3(nA, nB)) {
|
if (!veq3(nA, nB)) {
|
||||||
let tangent = vec._normalize((vec.cross(nA, nB)));
|
const tangent = vec._normalize((vec.cross(nA, nB)));
|
||||||
let auxInverse = i === points.length - 1;
|
const auxInverse = i === points.length - 1;
|
||||||
let auxPt = auxInverse ? points[i - 1] : points[i + 1];
|
const auxPt = auxInverse ? points[i - 1] : points[i + 1];
|
||||||
|
|
||||||
let segV = vec.sub(auxPt, pt);
|
const segV = vec.sub(auxPt, pt);
|
||||||
let dV = vec.mul(nA, - vec.dot(nA, segV));
|
const dV = vec.mul(nA, - vec.dot(nA, segV));
|
||||||
let projectionOntoTangentPlane = vec._add(dV, auxPt);
|
const projectionOntoTangentPlane = vec._add(dV, auxPt);
|
||||||
if (auxInverse) {
|
if (auxInverse) {
|
||||||
vec._negate(projectionOntoTangentPlane);
|
vec._negate(projectionOntoTangentPlane);
|
||||||
}
|
}
|
||||||
let estimatedTangent = vec._normalize(vec._sub(projectionOntoTangentPlane, pt));
|
const estimatedTangent = vec._normalize(vec._sub(projectionOntoTangentPlane, pt));
|
||||||
if (vec.dot(tangent, estimatedTangent) < 0) {
|
if (vec.dot(tangent, estimatedTangent) < 0) {
|
||||||
points.reverse();
|
points.reverse();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export default function newtonIterations(fnEval, x0, tol) {
|
||||||
let x = x0;
|
let x = x0;
|
||||||
|
|
||||||
for (let i = 0; i < MAX_IT; i++) {
|
for (let i = 0; i < MAX_IT; i++) {
|
||||||
let [fValue, dValue] = fnEval(x);
|
const [fValue, dValue] = fnEval(x);
|
||||||
if (Math.abs(fValue) <= tol) {
|
if (Math.abs(fValue) <= tol) {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
@ -31,7 +31,7 @@ export function newtonIterationsOnInterval(fnEval, a, b, tol) {
|
||||||
let x = a + (b - a) * 0.5;
|
let x = a + (b - a) * 0.5;
|
||||||
|
|
||||||
for (let i = 0; i < MAX_IT; i++) {
|
for (let i = 0; i < MAX_IT; i++) {
|
||||||
let [fValue, dValue] = fnEval(x);
|
const [fValue, dValue] = fnEval(x);
|
||||||
if (Math.abs(fValue) <= tol) {
|
if (Math.abs(fValue) <= tol) {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
@ -53,7 +53,7 @@ export function newtonIterationsOnIntervalExcluding(fnEval, a, b, tol) {
|
||||||
const xFn = t => a + (b-a)/(1 + Math.exp(-t));
|
const xFn = t => a + (b-a)/(1 + Math.exp(-t));
|
||||||
|
|
||||||
const xDer = t => {
|
const xDer = t => {
|
||||||
let et = Math.exp(-t);
|
const et = Math.exp(-t);
|
||||||
return et*(b-a)/sq(et+1);
|
return et*(b-a)/sq(et+1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -61,7 +61,7 @@ export function newtonIterationsOnIntervalExcluding(fnEval, a, b, tol) {
|
||||||
let t = 0;
|
let t = 0;
|
||||||
let x = xFn(t);
|
let x = xFn(t);
|
||||||
for (let i = 0; i < MAX_IT; i++) {
|
for (let i = 0; i < MAX_IT; i++) {
|
||||||
let [fValue, dValue] = fnEval(x);
|
const [fValue, dValue] = fnEval(x);
|
||||||
|
|
||||||
if (Math.abs(fValue) <= tol) {
|
if (Math.abs(fValue) <= tol) {
|
||||||
return x;
|
return x;
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,12 @@ export default function curveTess(curve, min, max, tessTol, scale) {
|
||||||
|
|
||||||
export function curveTessParams(curve, min, max, tessTol, scale) {
|
export function curveTessParams(curve, min, max, tessTol, scale) {
|
||||||
|
|
||||||
let out = [];
|
const out = [];
|
||||||
let knots = curve.knots();
|
const knots = curve.knots();
|
||||||
|
|
||||||
let splits = [min];
|
const splits = [min];
|
||||||
|
|
||||||
for (let split of knots) {
|
for (const split of knots) {
|
||||||
if (split > min && split < max) {
|
if (split > min && split < max) {
|
||||||
splits.push(split);
|
splits.push(split);
|
||||||
}
|
}
|
||||||
|
|
@ -20,14 +20,14 @@ export function curveTessParams(curve, min, max, tessTol, scale) {
|
||||||
|
|
||||||
function refine(u1, u2, step) {
|
function refine(u1, u2, step) {
|
||||||
if (step < u2 - u1) {
|
if (step < u2 - u1) {
|
||||||
let mid = u1 + (u2 - u1) * 0.5;
|
const mid = u1 + (u2 - u1) * 0.5;
|
||||||
refine(u1, mid, step);
|
refine(u1, mid, step);
|
||||||
out.push(mid);
|
out.push(mid);
|
||||||
refine(mid, u2, curveStep(curve, mid, tessTol, scale));
|
refine(mid, u2, curveStep(curve, mid, tessTol, scale));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let i = 1; i < splits.length; ++i) {
|
for (let i = 1; i < splits.length; ++i) {
|
||||||
let u1 = splits[i - 1];
|
const u1 = splits[i - 1];
|
||||||
out.push(u1);
|
out.push(u1);
|
||||||
refine(u1, splits[i], curveStep(curve, u1, tessTol, scale));
|
refine(u1, splits[i], curveStep(curve, u1, tessTol, scale));
|
||||||
}
|
}
|
||||||
|
|
@ -39,16 +39,16 @@ export function curveTessParams(curve, min, max, tessTol, scale) {
|
||||||
export function curveStep(curve, u, tessTol, scale) {
|
export function curveStep(curve, u, tessTol, scale) {
|
||||||
tessTol = tessTol || 1;
|
tessTol = tessTol || 1;
|
||||||
scale = scale || 1;
|
scale = scale || 1;
|
||||||
let ders = curve.eval(u, 2);
|
const ders = curve.eval(u, 2);
|
||||||
let r1 = ders[1];
|
const r1 = ders[1];
|
||||||
let r2 = ders[2];
|
const r2 = ders[2];
|
||||||
|
|
||||||
let r1lsq = vec.lengthSq(r1);
|
const r1lsq = vec.lengthSq(r1);
|
||||||
let r1l = Math.sqrt(r1lsq);
|
const r1l = Math.sqrt(r1lsq);
|
||||||
|
|
||||||
let r = r1lsq * r1l / vec.length(vec.cross(r1, r2));
|
const r = r1lsq * r1l / vec.length(vec.cross(r1, r2));
|
||||||
let tol = tessTol / scale;
|
const tol = tessTol / scale;
|
||||||
|
|
||||||
let step = 2 * Math.sqrt(tol*(2*r - tol)) / r1l;
|
const step = 2 * Math.sqrt(tol*(2*r - tol)) / r1l;
|
||||||
return step;
|
return step;
|
||||||
}
|
}
|
||||||
|
|
@ -5,20 +5,20 @@ import {areEqual} from "math/equality";
|
||||||
|
|
||||||
export default function curveIntersect(curve1, curve2, isecRange1, isecRange2, tesselator) {
|
export default function curveIntersect(curve1, curve2, isecRange1, isecRange2, tesselator) {
|
||||||
|
|
||||||
let result = [];
|
const result = [];
|
||||||
let segs1 = tesselator(curve1, isecRange1[0], isecRange1[1]);
|
const segs1 = tesselator(curve1, isecRange1[0], isecRange1[1]);
|
||||||
let segs2 = tesselator(curve2, isecRange2[0], isecRange2[1]);
|
const segs2 = tesselator(curve2, isecRange2[0], isecRange2[1]);
|
||||||
|
|
||||||
for (let i = 0; i < segs1.length - 1; i++) {
|
for (let i = 0; i < segs1.length - 1; i++) {
|
||||||
let a1 = segs1[i];
|
const a1 = segs1[i];
|
||||||
let b1 = segs1[i + 1];
|
const b1 = segs1[i + 1];
|
||||||
for (let j = 0; j < segs2.length - 1; j++) {
|
for (let j = 0; j < segs2.length - 1; j++) {
|
||||||
let a2 = segs2[j];
|
const a2 = segs2[j];
|
||||||
let b2 = segs2[j + 1];
|
const b2 = segs2[j + 1];
|
||||||
|
|
||||||
let isec = intersectSegs(a1, b1, a2, b2, TOLERANCE);
|
const isec = intersectSegs(a1, b1, a2, b2, TOLERANCE);
|
||||||
if (isec !== null) {
|
if (isec !== null) {
|
||||||
let {point1, point2, l1, l2} = isec;
|
const {point1, point2, l1, l2} = isec;
|
||||||
|
|
||||||
let u1 = curve1.param(point1);
|
let u1 = curve1.param(point1);
|
||||||
let u2 = curve2.param(point2);
|
let u2 = curve2.param(point2);
|
||||||
|
|
@ -52,19 +52,19 @@ function curveExactIntersection(curve1, curve2, u1, u2) {
|
||||||
return vec.lengthSq( vec.sub(curve1.point(u1), curve2.point(u2)));
|
return vec.lengthSq( vec.sub(curve1.point(u1), curve2.point(u2)));
|
||||||
}
|
}
|
||||||
function grad([u1, u2]) {
|
function grad([u1, u2]) {
|
||||||
let d1 = curve1.eval( u1, 1);
|
const d1 = curve1.eval( u1, 1);
|
||||||
let d2 = curve2.eval( u2, 1);
|
const d2 = curve2.eval( u2, 1);
|
||||||
let r = vec.sub(d1[0], d2[0]);
|
const r = vec.sub(d1[0], d2[0]);
|
||||||
let drdu = d1[1];
|
const drdu = d1[1];
|
||||||
let drdt = vec.mul(-1, d2[1]);
|
const drdt = vec.mul(-1, d2[1]);
|
||||||
return [2 * vec.dot(drdu, r), 2 * vec.dot(drdt,r)];
|
return [2 * vec.dot(drdu, r), 2 * vec.dot(drdt,r)];
|
||||||
}
|
}
|
||||||
let params = [u1, u2];
|
const params = [u1, u2];
|
||||||
return fmin_bfgs(f, params, TOLERANCE_SQ, grad).solution;
|
return fmin_bfgs(f, params, TOLERANCE_SQ, grad).solution;
|
||||||
}
|
}
|
||||||
|
|
||||||
function lineLineIntersection(p1, p2, v1, v2) {
|
function lineLineIntersection(p1, p2, v1, v2) {
|
||||||
let zAx = vec.cross(v1, v2);
|
const zAx = vec.cross(v1, v2);
|
||||||
const n1 = vec._normalize(vec.cross(zAx, v1));
|
const n1 = vec._normalize(vec.cross(zAx, v1));
|
||||||
const n2 = vec._normalize(vec.cross(zAx, v2));
|
const n2 = vec._normalize(vec.cross(zAx, v2));
|
||||||
return {
|
return {
|
||||||
|
|
@ -74,18 +74,18 @@ function lineLineIntersection(p1, p2, v1, v2) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function intersectSegs(a1, b1, a2, b2) {
|
function intersectSegs(a1, b1, a2, b2) {
|
||||||
let v1 = vec.sub(b1, a1);
|
const v1 = vec.sub(b1, a1);
|
||||||
let v2 = vec.sub(b2, a2);
|
const v2 = vec.sub(b2, a2);
|
||||||
let l1 = vec.length(v1);
|
const l1 = vec.length(v1);
|
||||||
let l2 = vec.length(v2);
|
const l2 = vec.length(v2);
|
||||||
vec._div(v1, l1);
|
vec._div(v1, l1);
|
||||||
vec._div(v2, l2);
|
vec._div(v2, l2);
|
||||||
|
|
||||||
let {u1, u2} = lineLineIntersection(a1, a2, v1, v2);
|
const {u1, u2} = lineLineIntersection(a1, a2, v1, v2);
|
||||||
let point1 = vec.add(a1, vec.mul(v1, u1));
|
const point1 = vec.add(a1, vec.mul(v1, u1));
|
||||||
let point2 = vec.add(a2, vec.mul(v2, u2));
|
const point2 = vec.add(a2, vec.mul(v2, u2));
|
||||||
let p2p = vec.lengthSq(vec.sub(point1, point2));
|
const p2p = vec.lengthSq(vec.sub(point1, point2));
|
||||||
let eq = (a, b) => areEqual(a, b, TOLERANCE);
|
const eq = (a, b) => areEqual(a, b, TOLERANCE);
|
||||||
if (u1 !== Infinity && u2 !== Infinity && areEqual(p2p, 0, TOLERANCE_SQ) &&
|
if (u1 !== Infinity && u2 !== Infinity && areEqual(p2p, 0, TOLERANCE_SQ) &&
|
||||||
((u1 >0 && u1 < l1) || eq(u1, 0) || eq(u1, l1)) &&
|
((u1 >0 && u1 < l1) || eq(u1, 0) || eq(u1, l1)) &&
|
||||||
((u2 >0 && u2 < l2) || eq(u2, 0) || eq(u2, l2))
|
((u2 >0 && u2 < l2) || eq(u2, 0) || eq(u2, l2))
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ export function surfaceIntersect(surfaceA, surfaceB) {
|
||||||
|
|
||||||
function fixTessNaNPoitns(s, tess) {
|
function fixTessNaNPoitns(s, tess) {
|
||||||
for (let i = 0; i < tess.points.length; i++) {
|
for (let i = 0; i < tess.points.length; i++) {
|
||||||
let pt = tess.points[i];
|
const pt = tess.points[i];
|
||||||
if (Number.isNaN(pt[0]) || Number.isNaN(pt[1]) || Number.isNaN(pt[2])) {
|
if (Number.isNaN(pt[0]) || Number.isNaN(pt[1]) || Number.isNaN(pt[2])) {
|
||||||
let [u, v] = tess.uvs[i];
|
const [u, v] = tess.uvs[i];
|
||||||
tess.points[i] = verb.eval.Eval.rationalSurfacePoint(s, u, v);
|
tess.points[i] = verb.eval.Eval.rationalSurfacePoint(s, u, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -25,8 +25,8 @@ export function surfaceIntersect(surfaceA, surfaceB) {
|
||||||
verb.eval.Intersect.surfacesAtPointWithEstimate(surfaceA, surfaceB, inter.uv0, inter.uv1, NUMERICAL_SOLVE_TOL)
|
verb.eval.Intersect.surfacesAtPointWithEstimate(surfaceA, surfaceB, inter.uv0, inter.uv1, NUMERICAL_SOLVE_TOL)
|
||||||
));
|
));
|
||||||
|
|
||||||
let curves = [];
|
const curves = [];
|
||||||
for (let pl of exactPls) {
|
for (const pl of exactPls) {
|
||||||
let points = pl.map(ip => ip.point);
|
let points = pl.map(ip => ip.point);
|
||||||
|
|
||||||
points = removeSuperfluousPoints(points, 30*30); //5*5
|
points = removeSuperfluousPoints(points, 30*30); //5*5
|
||||||
|
|
@ -39,25 +39,25 @@ export function surfaceIntersect(surfaceA, surfaceB) {
|
||||||
//it's Douglas–Peucker and it's not well suited here
|
//it's Douglas–Peucker and it's not well suited here
|
||||||
function removeSuperfluousPoints(points, tolSq) {
|
function removeSuperfluousPoints(points, tolSq) {
|
||||||
|
|
||||||
let out = [];
|
const out = [];
|
||||||
let stack = [[0, points.length - 1]];
|
const stack = [[0, points.length - 1]];
|
||||||
out.push(points[0]);
|
out.push(points[0]);
|
||||||
while (stack.length !== 0) {
|
while (stack.length !== 0) {
|
||||||
let stackItem = stack.pop();
|
const stackItem = stack.pop();
|
||||||
if (!Array.isArray(stackItem)) {
|
if (!Array.isArray(stackItem)) {
|
||||||
out.push(points[stackItem]);
|
out.push(points[stackItem]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let [from, to] = stackItem;
|
const [from, to] = stackItem;
|
||||||
let maxDistSq = tolSq;
|
let maxDistSq = tolSq;
|
||||||
let hero = -1;
|
let hero = -1;
|
||||||
let v = vec._normalize(vec.sub(points[to], points[from]));
|
const v = vec._normalize(vec.sub(points[to], points[from]));
|
||||||
|
|
||||||
for (let i = from + 1; i < to; i ++) {
|
for (let i = from + 1; i < to; i ++) {
|
||||||
let proj = vec.dot(v, vec.sub(points[i], points[from]));
|
const proj = vec.dot(v, vec.sub(points[i], points[from]));
|
||||||
let vA = vec.add(points[from], vec.mul(v, proj));
|
const vA = vec.add(points[from], vec.mul(v, proj));
|
||||||
let vX = vec.sub(points[i], vA);
|
const vX = vec.sub(points[i], vA);
|
||||||
let perpDistSq = vec.lengthSq(vX);
|
const perpDistSq = vec.lengthSq(vX);
|
||||||
if (perpDistSq > maxDistSq) {
|
if (perpDistSq > maxDistSq) {
|
||||||
hero = i;
|
hero = i;
|
||||||
maxDistSq = perpDistSq;
|
maxDistSq = perpDistSq;
|
||||||
|
|
|
||||||
|
|
@ -14,19 +14,19 @@ export function surfaceSurfaceStablePoints(surfaceA, surfaceB) {
|
||||||
const X=0, Y=1, Z=2;
|
const X=0, Y=1, Z=2;
|
||||||
function squareDistanceFn(u) {
|
function squareDistanceFn(u) {
|
||||||
|
|
||||||
let [f, d1, d2] = curve.eval(u, 2);
|
const [f, d1, d2] = curve.eval(u, 2);
|
||||||
|
|
||||||
let r1Comp = i => 2 * f[i] * d1[i] - 2 * f[i] * d1[i];
|
const r1Comp = i => 2 * f[i] * d1[i] - 2 * f[i] * d1[i];
|
||||||
let r2Comp = i => 2 * f[i] * d2[i] + 2 * d1[i] * d1[i] - 2 * f[i] * d2[i];
|
const r2Comp = i => 2 * f[i] * d2[i] + 2 * d1[i] * d1[i] - 2 * f[i] * d2[i];
|
||||||
|
|
||||||
let r1 = r1Comp(X) + r1Comp(Y) + r1Comp(Z);
|
const r1 = r1Comp(X) + r1Comp(Y) + r1Comp(Z);
|
||||||
let r2 = r2Comp(X) + r2Comp(Y) + r2Comp(Z);
|
const r2 = r2Comp(X) + r2Comp(Y) + r2Comp(Z);
|
||||||
|
|
||||||
return [r1, r2];
|
return [r1, r2];
|
||||||
}
|
}
|
||||||
|
|
||||||
let intMin = 0;
|
const intMin = 0;
|
||||||
let intMax = 0;
|
const intMax = 0;
|
||||||
return newtonIterationsOnInterval(squareDistanceFn, intMin, intMax, 1e-5);
|
return newtonIterationsOnInterval(squareDistanceFn, intMin, intMax, 1e-5);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ class Tree {
|
||||||
if (this.isLeaf()) {
|
if (this.isLeaf()) {
|
||||||
callback(this);
|
callback(this);
|
||||||
} else {
|
} else {
|
||||||
for (let child of this.children) {
|
for (const child of this.children) {
|
||||||
child.leafs(callback);
|
child.leafs(callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -230,14 +230,14 @@ export function refine(tiles, opts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tile.children != null) {
|
if (tile.children != null) {
|
||||||
for (let subTile of tile.children) {
|
for (const subTile of tile.children) {
|
||||||
check(subTile, uLevel, vLevel);
|
check(subTile, uLevel, vLevel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let row of tiles) {
|
for (const row of tiles) {
|
||||||
for (let tile of row) {
|
for (const tile of row) {
|
||||||
check(tile, 0, 0);
|
check(tile, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ export class StreamBase {
|
||||||
if (!usingStream) {
|
if (!usingStream) {
|
||||||
usingStream = StateStream;
|
usingStream = StateStream;
|
||||||
}
|
}
|
||||||
let stateStream = new usingStream(initialValue);
|
const stateStream = new usingStream(initialValue);
|
||||||
this.attach(v => stateStream.next(v));
|
this.attach(v => stateStream.next(v));
|
||||||
return stateStream;
|
return stateStream;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ export class CombineStream extends StreamBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
attach(observer) {
|
attach(observer) {
|
||||||
let detachers = new Array(this.streams.length);
|
const detachers = new Array(this.streams.length);
|
||||||
this.streams.forEach((s, i) => {
|
this.streams.forEach((s, i) => {
|
||||||
detachers[i] = s.attach(value => {
|
detachers[i] = s.attach(value => {
|
||||||
this.values[i] = value;
|
this.values[i] = value;
|
||||||
|
|
@ -32,7 +32,7 @@ export class CombineStream extends StreamBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
isReady() {
|
isReady() {
|
||||||
for (let val of this.values) {
|
for (const val of this.values) {
|
||||||
if (val === NOT_INITIALIZED) {
|
if (val === NOT_INITIALIZED) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ export class MergeStream extends StreamBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
attach(observer) {
|
attach(observer) {
|
||||||
let detachers = new Array(this.streams.length);
|
const detachers = new Array(this.streams.length);
|
||||||
this.streams.forEach((s, i) => {
|
this.streams.forEach((s, i) => {
|
||||||
detachers[i] = s.attach(observer);
|
detachers[i] = s.attach(observer);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@ export function pointAsText(point) {
|
||||||
|
|
||||||
export function renderPointImpl(point, renderer) {
|
export function renderPointImpl(point, renderer) {
|
||||||
if (Array.isArray(point)) {
|
if (Array.isArray(point)) {
|
||||||
let [x, y, z] = point;
|
const [x, y, z] = point;
|
||||||
return renderer(x, y, z);
|
return renderer(x, y, z);
|
||||||
} else {
|
} else {
|
||||||
let {x, y, z} = point;
|
const {x, y, z} = point;
|
||||||
return renderer(x, y, z);
|
return renderer(x, y, z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +26,7 @@ function toInt(num) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const hex = v => {
|
const hex = v => {
|
||||||
let r = toInt(v) % 255;
|
const r = toInt(v) % 255;
|
||||||
let s = r.toString(16);
|
let s = r.toString(16);
|
||||||
if (s.length === 1) {
|
if (s.length === 1) {
|
||||||
s = '0' + s;
|
s = '0' + s;
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,14 @@ export default function(container) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let xAxis = createBasisArrow(AXIS.X, 0xFF0000);
|
const xAxis = createBasisArrow(AXIS.X, 0xFF0000);
|
||||||
let yAxis = createBasisArrow(AXIS.Y, 0x00FF00);
|
const yAxis = createBasisArrow(AXIS.Y, 0x00FF00);
|
||||||
let zAxis = createBasisArrow(AXIS.Z, 0x0000FF);
|
const zAxis = createBasisArrow(AXIS.Z, 0x0000FF);
|
||||||
|
|
||||||
let root = SceneGraph.createGroup();
|
const root = SceneGraph.createGroup();
|
||||||
let csys = SceneGraph.createGroup();
|
const csys = SceneGraph.createGroup();
|
||||||
|
|
||||||
let scene = new Scene();
|
const scene = new Scene();
|
||||||
csys.add(xAxis);
|
csys.add(xAxis);
|
||||||
csys.add(yAxis);
|
csys.add(yAxis);
|
||||||
csys.add(zAxis);
|
csys.add(zAxis);
|
||||||
|
|
@ -32,20 +32,20 @@ export default function(container) {
|
||||||
root.add(csys);
|
root.add(csys);
|
||||||
scene.add(root);
|
scene.add(root);
|
||||||
|
|
||||||
let ambientLight = new AmbientLight(0x0f0f0f);
|
const ambientLight = new AmbientLight(0x0f0f0f);
|
||||||
scene.add(ambientLight);
|
scene.add(ambientLight);
|
||||||
|
|
||||||
let spotLight = new SpotLight(0xffffff);
|
const spotLight = new SpotLight(0xffffff);
|
||||||
spotLight.position.set(0, 0, 5);
|
spotLight.position.set(0, 0, 5);
|
||||||
spotLight.castShadow = true;
|
spotLight.castShadow = true;
|
||||||
scene.add(spotLight);
|
scene.add(spotLight);
|
||||||
|
|
||||||
let camera = new PerspectiveCamera( 25, 1, 0.1, 2000 );
|
const camera = new PerspectiveCamera( 25, 1, 0.1, 2000 );
|
||||||
camera.position.x = 0;
|
camera.position.x = 0;
|
||||||
camera.position.y = 0;
|
camera.position.y = 0;
|
||||||
camera.position.z = 5;
|
camera.position.z = 5;
|
||||||
|
|
||||||
let renderer = new WebGLRenderer({ alpha: true });
|
const renderer = new WebGLRenderer({ alpha: true });
|
||||||
renderer.setPixelRatio(DPR);
|
renderer.setPixelRatio(DPR);
|
||||||
// renderer.setClearColor(0x000000, 1);
|
// renderer.setClearColor(0x000000, 1);
|
||||||
// renderer.setClearAlpha(0);
|
// renderer.setClearAlpha(0);
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@
|
||||||
|
|
||||||
export function CADTrackballControls( object, domElement ) {
|
export function CADTrackballControls( object, domElement ) {
|
||||||
|
|
||||||
let _this = this;
|
const _this = this;
|
||||||
let STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
|
const STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
|
||||||
|
|
||||||
this.object = object;
|
this.object = object;
|
||||||
this.domElement = ( domElement !== undefined ) ? domElement : document;
|
this.domElement = ( domElement !== undefined ) ? domElement : document;
|
||||||
|
|
@ -47,9 +47,9 @@ export function CADTrackballControls( object, domElement ) {
|
||||||
this.projectionChanged = false;
|
this.projectionChanged = false;
|
||||||
this.projectionZoomSpeed = 0.5;
|
this.projectionZoomSpeed = 0.5;
|
||||||
|
|
||||||
let EPS = 0.000001;
|
const EPS = 0.000001;
|
||||||
|
|
||||||
let lastPosition = new THREE.Vector3();
|
const lastPosition = new THREE.Vector3();
|
||||||
|
|
||||||
let _state = STATE.NONE,
|
let _state = STATE.NONE,
|
||||||
_prevState = STATE.NONE,
|
_prevState = STATE.NONE,
|
||||||
|
|
@ -79,8 +79,8 @@ export function CADTrackballControls( object, domElement ) {
|
||||||
|
|
||||||
// events
|
// events
|
||||||
|
|
||||||
let startEvent = { type: 'start' };
|
const startEvent = { type: 'start' };
|
||||||
let endEvent = { type: 'end' };
|
const endEvent = { type: 'end' };
|
||||||
|
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
|
|
@ -96,9 +96,9 @@ export function CADTrackballControls( object, domElement ) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
let box = this.domElement.getBoundingClientRect();
|
const box = this.domElement.getBoundingClientRect();
|
||||||
// adjustments come from similar code in the jquery offset() function
|
// adjustments come from similar code in the jquery offset() function
|
||||||
let d = this.domElement.ownerDocument.documentElement;
|
const d = this.domElement.ownerDocument.documentElement;
|
||||||
this.screen.left = box.left + window.pageXOffset - d.clientLeft;
|
this.screen.left = box.left + window.pageXOffset - d.clientLeft;
|
||||||
this.screen.top = box.top + window.pageYOffset - d.clientTop;
|
this.screen.top = box.top + window.pageYOffset - d.clientTop;
|
||||||
this.screen.width = box.width;
|
this.screen.width = box.width;
|
||||||
|
|
@ -118,9 +118,9 @@ export function CADTrackballControls( object, domElement ) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let getMouseOnScreen = ( function () {
|
const getMouseOnScreen = ( function () {
|
||||||
|
|
||||||
let vector = new THREE.Vector2();
|
const vector = new THREE.Vector2();
|
||||||
|
|
||||||
return function getMouseOnScreen( pageX, pageY ) {
|
return function getMouseOnScreen( pageX, pageY ) {
|
||||||
|
|
||||||
|
|
@ -135,9 +135,9 @@ export function CADTrackballControls( object, domElement ) {
|
||||||
|
|
||||||
}() );
|
}() );
|
||||||
|
|
||||||
let getMouseOnCircle = ( function () {
|
const getMouseOnCircle = ( function () {
|
||||||
|
|
||||||
let vector = new THREE.Vector2();
|
const vector = new THREE.Vector2();
|
||||||
|
|
||||||
return function getMouseOnCircle( pageX, pageY ) {
|
return function getMouseOnCircle( pageX, pageY ) {
|
||||||
|
|
||||||
|
|
@ -249,7 +249,7 @@ export function CADTrackballControls( object, domElement ) {
|
||||||
|
|
||||||
this.panCamera = ( function() {
|
this.panCamera = ( function() {
|
||||||
|
|
||||||
let mouseChange = new THREE.Vector2(),
|
const mouseChange = new THREE.Vector2(),
|
||||||
objectUp = new THREE.Vector3(),
|
objectUp = new THREE.Vector3(),
|
||||||
pan = new THREE.Vector3();
|
pan = new THREE.Vector3();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import {ArrowHelper, CylinderBufferGeometry, Mesh, MeshBasicMaterial, Object3D,
|
||||||
import {createMeshLineGeometry} from './meshLine';
|
import {createMeshLineGeometry} from './meshLine';
|
||||||
|
|
||||||
export function createArrow(length, arrowLength, arrowHead, axis, color, opacity, materialMixins) {
|
export function createArrow(length, arrowLength, arrowHead, axis, color, opacity, materialMixins) {
|
||||||
let arrow = new ArrowHelper(new Vector3().copy(axis), new Vector3(0, 0, 0), length, color, arrowLength, arrowHead);
|
const arrow = new ArrowHelper(new Vector3().copy(axis), new Vector3(0, 0, 0), length, color, arrowLength, arrowHead);
|
||||||
arrow.updateMatrix();
|
arrow.updateMatrix();
|
||||||
arrow.line.material.linewidth = 1 / DPR;
|
arrow.line.material.linewidth = 1 / DPR;
|
||||||
if (opacity !== undefined) {
|
if (opacity !== undefined) {
|
||||||
|
|
@ -42,11 +42,11 @@ export class MeshArrow extends Object3D {
|
||||||
|
|
||||||
// dir is assumed to be normalized
|
// dir is assumed to be normalized
|
||||||
|
|
||||||
let cone = new Mesh(tipGeometry, materialCreate({color}));
|
const cone = new Mesh(tipGeometry, materialCreate({color}));
|
||||||
cone.matrixAutoUpdate = false;
|
cone.matrixAutoUpdate = false;
|
||||||
this.add(cone);
|
this.add(cone);
|
||||||
|
|
||||||
let line = new Mesh(lineGeometry, materialCreate({color}));
|
const line = new Mesh(lineGeometry, materialCreate({color}));
|
||||||
line.matrixAutoUpdate = false;
|
line.matrixAutoUpdate = false;
|
||||||
this.add(line);
|
this.add(line);
|
||||||
|
|
||||||
|
|
@ -62,7 +62,7 @@ export class MeshArrow extends Object3D {
|
||||||
} else if (dir.y < -0.99999) {
|
} else if (dir.y < -0.99999) {
|
||||||
this.quaternion.set(1, 0, 0, 0);
|
this.quaternion.set(1, 0, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
let axis = new Vector3();
|
const axis = new Vector3();
|
||||||
let radians;
|
let radians;
|
||||||
axis.set(dir.z, 0, -dir.x).normalize();
|
axis.set(dir.z, 0, -dir.x).normalize();
|
||||||
radians = Math.acos(dir.y);
|
radians = Math.acos(dir.y);
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,11 @@ export function createMeshLineGeometry(points, width) {
|
||||||
let base = null;
|
let base = null;
|
||||||
for (let i = 1; i < points.length; i++) {
|
for (let i = 1; i < points.length; i++) {
|
||||||
|
|
||||||
let a = points[i - 1];
|
const a = points[i - 1];
|
||||||
let b = points[i];
|
const b = points[i];
|
||||||
let ab = vec._normalize(vec.sub(b, a));
|
const ab = vec._normalize(vec.sub(b, a));
|
||||||
|
|
||||||
let dirs = [];
|
const dirs = [];
|
||||||
dirs[0] = perpendicularVector(ab);
|
dirs[0] = perpendicularVector(ab);
|
||||||
dirs[1] = vec.cross(ab, dirs[0]);
|
dirs[1] = vec.cross(ab, dirs[0]);
|
||||||
dirs[2] = vec.negate(dirs[0]);
|
dirs[2] = vec.negate(dirs[0]);
|
||||||
|
|
@ -23,9 +23,9 @@ export function createMeshLineGeometry(points, width) {
|
||||||
if (base === null) {
|
if (base === null) {
|
||||||
base = dirs.map(d => vec.add(a, d));
|
base = dirs.map(d => vec.add(a, d));
|
||||||
}
|
}
|
||||||
let lid = dirs.map(d => vec.add(b, d));
|
const lid = dirs.map(d => vec.add(b, d));
|
||||||
|
|
||||||
let off = vertices.length;
|
const off = vertices.length;
|
||||||
base.forEach(p => vertices.push(...p));
|
base.forEach(p => vertices.push(...p));
|
||||||
lid.forEach(p => vertices.push(...p));
|
lid.forEach(p => vertices.push(...p));
|
||||||
base = lid;
|
base = lid;
|
||||||
|
|
|
||||||
|
|
@ -11,14 +11,14 @@ export default class RaycastableArea extends Object3D {
|
||||||
|
|
||||||
raycast(raycaster, intersects ) {
|
raycast(raycaster, intersects ) {
|
||||||
//need to apply world matrix
|
//need to apply world matrix
|
||||||
let center = this.getCenter();
|
const center = this.getCenter();
|
||||||
let radius = this.getRadius();
|
const radius = this.getRadius();
|
||||||
let ray = raycaster.ray;
|
const ray = raycaster.ray;
|
||||||
let vec = this._vec;
|
const vec = this._vec;
|
||||||
let proj = vec.copy(center).subtract(ray.center).dot(ray.dir);
|
const proj = vec.copy(center).subtract(ray.center).dot(ray.dir);
|
||||||
vec.copy(ray.dir).multiplyScalar(proj).add(ray.center);
|
vec.copy(ray.dir).multiplyScalar(proj).add(ray.center);
|
||||||
|
|
||||||
let distSq = vec.distanceToSquared(center);
|
const distSq = vec.distanceToSquared(center);
|
||||||
if (distSq <= radius * this) {
|
if (distSq <= radius * this) {
|
||||||
intersects.push({
|
intersects.push({
|
||||||
distance: Math.sqrt(distSq),
|
distance: Math.sqrt(distSq),
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ function createMaterial(sceneSetup, color, width, opacity, ambient, offset) {
|
||||||
function createGeometry(tessellation) {
|
function createGeometry(tessellation) {
|
||||||
|
|
||||||
const positions = [];
|
const positions = [];
|
||||||
for ( let point of tessellation ) {
|
for ( const point of tessellation ) {
|
||||||
positions.push( ...point );
|
positions.push( ...point );
|
||||||
}
|
}
|
||||||
const geometry = new LineGeometry();
|
const geometry = new LineGeometry();
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
|
|
||||||
export function setBasisToObject3D(obj, basis, depth) {
|
export function setBasisToObject3D(obj, basis, depth) {
|
||||||
obj.matrix.identity();
|
obj.matrix.identity();
|
||||||
let mx = new THREE.Matrix4();
|
const mx = new THREE.Matrix4();
|
||||||
mx.makeBasis(basis[0].three(), basis[1].three(), basis[2].three());
|
mx.makeBasis(basis[0].three(), basis[1].three(), basis[2].three());
|
||||||
let depthOff = new THREE.Vector3(0, 0, depth);
|
const depthOff = new THREE.Vector3(0, 0, depth);
|
||||||
depthOff.applyMatrix4(mx);
|
depthOff.applyMatrix4(mx);
|
||||||
mx.setPosition(depthOff);
|
mx.setPosition(depthOff);
|
||||||
obj.applyMatrix(mx);
|
obj.applyMatrix(mx);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setCadToViewMatrix(cadMatrix, threeMatrix) {
|
export function setCadToViewMatrix(cadMatrix, threeMatrix) {
|
||||||
let cm = cadMatrix;
|
const cm = cadMatrix;
|
||||||
threeMatrix.set(
|
threeMatrix.set(
|
||||||
cm.mxx, cm.mxy, cm.mxz, cm.tx,
|
cm.mxx, cm.mxy, cm.mxz, cm.tx,
|
||||||
cm.myx, cm.myy, cm.myz, cm.ty,
|
cm.myx, cm.myy, cm.myz, cm.ty,
|
||||||
|
|
|
||||||
|
|
@ -2,21 +2,21 @@ import {Object3D, Vector3} from 'three';
|
||||||
import DPR from '../dpr';
|
import DPR from '../dpr';
|
||||||
|
|
||||||
export function viewScaleFactor(sceneSetup, origin, SIZE_PX, SIZE_MODEL) {
|
export function viewScaleFactor(sceneSetup, origin, SIZE_PX, SIZE_MODEL) {
|
||||||
let container = sceneSetup.container;
|
const container = sceneSetup.container;
|
||||||
let viewHeight = container.clientHeight;
|
const viewHeight = container.clientHeight;
|
||||||
let camera = sceneSetup.camera;
|
const camera = sceneSetup.camera;
|
||||||
|
|
||||||
if (camera.isOrthographicCamera) {
|
if (camera.isOrthographicCamera) {
|
||||||
return viewHeight / (camera.top - camera.bottom) / camera.zoom * 2 * DPR * SIZE_PX / SIZE_MODEL;
|
return viewHeight / (camera.top - camera.bottom) / camera.zoom * 2 * DPR * SIZE_PX / SIZE_MODEL;
|
||||||
} else {
|
} else {
|
||||||
let p = new Vector3().copy(origin);
|
const p = new Vector3().copy(origin);
|
||||||
let cp = new Vector3().copy(camera.position);
|
const cp = new Vector3().copy(camera.position);
|
||||||
let z = p.sub(cp).length();
|
const z = p.sub(cp).length();
|
||||||
let tanHFov = Math.atan((camera.fov / 2) / 180 * Math.PI);
|
const tanHFov = Math.atan((camera.fov / 2) / 180 * Math.PI);
|
||||||
let fitUnits = tanHFov * z * 2;
|
const fitUnits = tanHFov * z * 2;
|
||||||
|
|
||||||
let modelTakingPart = SIZE_MODEL / fitUnits;
|
const modelTakingPart = SIZE_MODEL / fitUnits;
|
||||||
let modelActualSizePx = viewHeight * modelTakingPart;
|
const modelActualSizePx = viewHeight * modelTakingPart;
|
||||||
return SIZE_PX / modelActualSizePx;
|
return SIZE_PX / modelActualSizePx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -38,7 +38,7 @@ export class ConstantScaleGroup extends Object3D {
|
||||||
updateMatrix() {
|
updateMatrix() {
|
||||||
// let {origin: o, x, y, z} = this.csys;
|
// let {origin: o, x, y, z} = this.csys;
|
||||||
//
|
//
|
||||||
let k = viewScaleFactor(this.sceneSetup, this.getOrigin(), this.sizePx, this.sizeModel);
|
const k = viewScaleFactor(this.sceneSetup, this.getOrigin(), this.sizePx, this.sizeModel);
|
||||||
|
|
||||||
this.scale.set(k,k,k);
|
this.scale.set(k,k,k);
|
||||||
super.updateMatrix();
|
super.updateMatrix();
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export function clearGroup(group) {
|
||||||
|
|
||||||
|
|
||||||
export function findAncestor( obj, predicate, includeItself ) {
|
export function findAncestor( obj, predicate, includeItself ) {
|
||||||
let parent = includeItself ? obj : obj.parent;
|
const parent = includeItself ? obj : obj.parent;
|
||||||
if ( parent !== null ) {
|
if ( parent !== null ) {
|
||||||
if (predicate(parent)) {
|
if (predicate(parent)) {
|
||||||
return parent;
|
return parent;
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,9 @@ export class Adjuster extends React.Component {
|
||||||
if (!this.el) {
|
if (!this.el) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let w = this.el.clientWidth;
|
const w = this.el.clientWidth;
|
||||||
let h = this.el.clientHeight;
|
const h = this.el.clientHeight;
|
||||||
let holder = document.documentElement;
|
const holder = document.documentElement;
|
||||||
|
|
||||||
const fit = (prop, pos, dim, holderDim) => {
|
const fit = (prop, pos, dim, holderDim) => {
|
||||||
if (pos !== undefined) {
|
if (pos !== undefined) {
|
||||||
|
|
@ -59,7 +59,7 @@ export class Adjuster extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {left, top, right, bottom, children, style, zIndex, visible, centered, ...props} = this.props;
|
const {left, top, right, bottom, children, style, zIndex, visible, centered, ...props} = this.props;
|
||||||
return <div ref={el => this.el = el}
|
return <div ref={el => this.el = el}
|
||||||
style={{
|
style={{
|
||||||
visibility: 'hidden',
|
visibility: 'hidden',
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ export function InnerFolder(props) {
|
||||||
const [closed, setClosed] = useState(null)
|
const [closed, setClosed] = useState(null)
|
||||||
|
|
||||||
function isClosed(){
|
function isClosed(){
|
||||||
let {closable, defaultClosed} = props;
|
const {closable, defaultClosed} = props;
|
||||||
if (!closable) return false;
|
if (!closable) return false;
|
||||||
return closable && (closed === null ? defaultClosed : closed)
|
return closable && (closed === null ? defaultClosed : closed)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ export function MenuItem({icon, label, hotKey, style, disabled, onClick, childre
|
||||||
hotKey = null;
|
hotKey = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let clickHandler = disabled ? undefined : (e) => {
|
const clickHandler = disabled ? undefined : (e) => {
|
||||||
closeAllUpPopups();
|
closeAllUpPopups();
|
||||||
onClick(e);
|
onClick(e);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ export class Section extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {label, nonClosable, children} = this.props;
|
const {label, nonClosable, children} = this.props;
|
||||||
let closed = this.isClosed();
|
const closed = this.isClosed();
|
||||||
return <TabContext.Consumer>
|
return <TabContext.Consumer>
|
||||||
{
|
{
|
||||||
tabs => <div className={ls.section} style={{paddingLeft: 10}}>
|
tabs => <div className={ls.section} style={{paddingLeft: 10}}>
|
||||||
|
|
@ -34,7 +34,7 @@ export class Section extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
isClosed() {
|
isClosed() {
|
||||||
let {nonClosable} = this.props;
|
const {nonClosable} = this.props;
|
||||||
if (nonClosable) return false;
|
if (nonClosable) return false;
|
||||||
return this.state.closed;
|
return this.state.closed;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React, {useContext} from 'react';
|
||||||
import {FieldId} from "ui/components/controls/Field";
|
import {FieldId} from "ui/components/controls/Field";
|
||||||
|
|
||||||
export default function CheckboxControl(props) {
|
export default function CheckboxControl(props) {
|
||||||
let {onChange, value} = props;
|
const {onChange, value} = props;
|
||||||
const fieldId = useContext(FieldId);
|
const fieldId = useContext(FieldId);
|
||||||
return <input id={fieldId}
|
return <input id={fieldId}
|
||||||
type='checkbox'
|
type='checkbox'
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import React from 'react';
|
||||||
export default class ComboBoxControl extends React.Component {
|
export default class ComboBoxControl extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {onChange, value, includeNonExistent, children} = this.props;
|
const {onChange, value, includeNonExistent, children} = this.props;
|
||||||
let nonExistent = null;
|
let nonExistent = null;
|
||||||
if (includeNonExistent) {
|
if (includeNonExistent) {
|
||||||
let needsInclusion = false;
|
let needsInclusion = false;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||||
|
|
||||||
export default function InputControl(inprops) {
|
export default function InputControl(inprops) {
|
||||||
|
|
||||||
let {type, inputRef, width, onWheel, ...props} = inprops;
|
const {type, inputRef, width, onWheel, ...props} = inprops;
|
||||||
|
|
||||||
const style = width&&{
|
const style = width&&{
|
||||||
width
|
width
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,15 @@ import InputControl from './InputControl';
|
||||||
|
|
||||||
export default function NumberControl(props) {
|
export default function NumberControl(props) {
|
||||||
|
|
||||||
let {onChange, onFocus, value, width, baseStep, round, min, max, accelerator, cycle} = props;
|
const {onChange, onFocus, value, width, baseStep, round, min, max, accelerator, cycle} = props;
|
||||||
|
|
||||||
const onChangeFromTarget = e => {
|
const onChangeFromTarget = e => {
|
||||||
onChange(e.target.value);
|
onChange(e.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onWheel = (e) => {
|
const onWheel = (e) => {
|
||||||
let delta = e.shiftKey ? e.deltaX : e.deltaY;
|
const delta = e.shiftKey ? e.deltaX : e.deltaY;
|
||||||
let step = baseStep * (e.shiftKey ? accelerator : 1);
|
const step = baseStep * (e.shiftKey ? accelerator : 1);
|
||||||
let val = parseFloat(e.target.value);
|
let val = parseFloat(e.target.value);
|
||||||
if (isNaN(val)) val = 0;
|
if (isNaN(val)) val = 0;
|
||||||
val = val + (delta < 0 ? -step : step);
|
val = val + (delta < 0 ? -step : step);
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ export default class RadioButtons extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RadioButton({value, label}, {radioButtonsGroupName, radioButtonsValue, radioButtonsOnChange}) {
|
export function RadioButton({value, label}, {radioButtonsGroupName, radioButtonsValue, radioButtonsOnChange}) {
|
||||||
let onChange = e => {
|
const onChange = e => {
|
||||||
radioButtonsOnChange(e.target.value)
|
radioButtonsOnChange(e.target.value)
|
||||||
};
|
};
|
||||||
label = label || value;
|
label = label || value;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import React from 'react';
|
||||||
export default class ReadOnlyValueControl extends React.Component {
|
export default class ReadOnlyValueControl extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {value, placeholder} = this.props;
|
const {value, placeholder} = this.props;
|
||||||
return <span>{value||placeholder}</span>;
|
return <span>{value||placeholder}</span>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import InputControl from './InputControl';
|
||||||
export default class TextControl extends React.Component {
|
export default class TextControl extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {onChange, value, onFocus} = this.props;
|
const {onChange, value, onFocus} = this.props;
|
||||||
return <InputControl type='text'
|
return <InputControl type='text'
|
||||||
value={value}
|
value={value}
|
||||||
onChange={e => onChange(e.target.value)} onFocus={onFocus} />
|
onChange={e => onChange(e.target.value)} onFocus={onFocus} />
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ export default function connect(streamProvider) {
|
||||||
state = {hasError: false, streamProps: {}};
|
state = {hasError: false, streamProps: {}};
|
||||||
|
|
||||||
UNSAFE_componentWillMount() {
|
UNSAFE_componentWillMount() {
|
||||||
let stream = streamProvider(context.streams, this.props);
|
const stream = streamProvider(context.streams, this.props);
|
||||||
this.detacher = stream.attach(data => {
|
this.detacher = stream.attach(data => {
|
||||||
this.setState({
|
this.setState({
|
||||||
hasError: false,
|
hasError: false,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
export default function decoratorChain() {
|
export default function decoratorChain() {
|
||||||
let decorators = Array.from(arguments);
|
const decorators = Array.from(arguments);
|
||||||
return function(Component) {
|
return function(Component) {
|
||||||
for (let i = decorators.length - 1; i >= 0; i --) {
|
for (let i = decorators.length - 1; i >= 0; i --) {
|
||||||
Component = decorators[i](Component);
|
Component = decorators[i](Component);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import context from 'cad/context';
|
||||||
export default function mapContext(mapper) {
|
export default function mapContext(mapper) {
|
||||||
return function (Component) {
|
return function (Component) {
|
||||||
return function ContextMapper(props) {
|
return function ContextMapper(props) {
|
||||||
let actions = mapper(context, props);
|
const actions = mapper(context, props);
|
||||||
return <Component {...actions} {...props} />
|
return <Component {...actions} {...props} />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
export function aboveElement(el) {
|
export function aboveElement(el) {
|
||||||
let r = el.getBoundingClientRect();
|
const r = el.getBoundingClientRect();
|
||||||
return {
|
return {
|
||||||
x: r.left,
|
x: r.left,
|
||||||
y: r.top
|
y: r.top
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
export function enableAnonymousActionHint(ctx) {
|
export function enableAnonymousActionHint(ctx) {
|
||||||
return function(actionId) {
|
return function(actionId) {
|
||||||
const {services, actionService} = ctx;
|
const {services, actionService} = ctx;
|
||||||
let {left, top} = services.dom.viewerContainer.getBoundingClientRect();
|
const {left, top} = services.dom.viewerContainer.getBoundingClientRect();
|
||||||
actionService.showHintFor({
|
actionService.showHintFor({
|
||||||
actionId,
|
actionId,
|
||||||
x: left + 100,
|
x: left + 100,
|
||||||
|
|
@ -10,7 +10,7 @@ export function enableAnonymousActionHint(ctx) {
|
||||||
requester: 'anonymous'
|
requester: 'anonymous'
|
||||||
});
|
});
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
let value = actionService.hint$.value;
|
const value = actionService.hint$.value;
|
||||||
if (value && value.requester !== 'anonymous') {
|
if (value && value.requester !== 'anonymous') {
|
||||||
actionService.showHintFor(null);
|
actionService.showHintFor(null);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ export default [
|
||||||
info: 'switch camera mode between perspective and orthographic',
|
info: 'switch camera mode between perspective and orthographic',
|
||||||
},
|
},
|
||||||
invoke: context => {
|
invoke: context => {
|
||||||
let viewer = context.services.viewer;
|
const viewer = context.services.viewer;
|
||||||
viewer.toggleCamera();
|
viewer.toggleCamera();
|
||||||
viewer.render();
|
viewer.render();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,13 @@ const DIR_3_WAY_VIEW = new Vector(1, 1, 1).normalize();
|
||||||
const DIR_3_WAY_BACK_VIEW = new Vector(-1, 1, -1).normalize();
|
const DIR_3_WAY_BACK_VIEW = new Vector(-1, 1, -1).normalize();
|
||||||
|
|
||||||
export function lookAtFace(viewer, face, currFace) {
|
export function lookAtFace(viewer, face, currFace) {
|
||||||
let dist = currFace ? currFace.csys.origin.distanceTo(viewer.sceneSetup.camera.position) : undefined;
|
const dist = currFace ? currFace.csys.origin.distanceTo(viewer.sceneSetup.camera.position) : undefined;
|
||||||
viewer.lookAt(face.csys.origin, face.csys.z, face.csys.y, dist);
|
viewer.lookAt(face.csys.origin, face.csys.z, face.csys.y, dist);
|
||||||
viewer.requestRender();
|
viewer.requestRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
function faceAt(shells, shell, pos) {
|
function faceAt(shells, shell, pos) {
|
||||||
let shellIndex = shells.indexOf(shell);
|
const shellIndex = shells.indexOf(shell);
|
||||||
if (pos >= shell.faces.length) {
|
if (pos >= shell.faces.length) {
|
||||||
let i = shellIndex;
|
let i = shellIndex;
|
||||||
do {
|
do {
|
||||||
|
|
@ -37,9 +37,9 @@ function faceAt(shells, shell, pos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCurrentSelectedOrFirstFace(ctx) {
|
function getCurrentSelectedOrFirstFace(ctx) {
|
||||||
let face = ctx.services.selection.face.single;
|
const face = ctx.services.selection.face.single;
|
||||||
if (!face) {
|
if (!face) {
|
||||||
for (let shell of ctx.services.cadRegistry.shells) {
|
for (const shell of ctx.services.cadRegistry.shells) {
|
||||||
if (shell.faces.length !== 0) {
|
if (shell.faces.length !== 0) {
|
||||||
return shell.faces[0];
|
return shell.faces[0];
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +72,7 @@ export default [
|
||||||
},
|
},
|
||||||
|
|
||||||
invoke: ctx => {
|
invoke: ctx => {
|
||||||
let face = ctx.services.selection.face.single;
|
const face = ctx.services.selection.face.single;
|
||||||
if (face) {
|
if (face) {
|
||||||
lookAtFace(ctx.services.viewer, face);
|
lookAtFace(ctx.services.viewer, face);
|
||||||
}
|
}
|
||||||
|
|
@ -81,10 +81,10 @@ export default [
|
||||||
{
|
{
|
||||||
id: 'CycleFacesNext',
|
id: 'CycleFacesNext',
|
||||||
invoke: ctx => {
|
invoke: ctx => {
|
||||||
let face = getCurrentSelectedOrFirstFace(ctx);
|
const face = getCurrentSelectedOrFirstFace(ctx);
|
||||||
if (face) {
|
if (face) {
|
||||||
let index = face.shell.faces.indexOf(face);
|
const index = face.shell.faces.indexOf(face);
|
||||||
let nextFace = faceAt(ctx.services.cadRegistry.shells, face.shell, index + 1);
|
const nextFace = faceAt(ctx.services.cadRegistry.shells, face.shell, index + 1);
|
||||||
ctx.services.pickControl.pick(nextFace);
|
ctx.services.pickControl.pick(nextFace);
|
||||||
lookAtFace(ctx.services.viewer, nextFace, face);
|
lookAtFace(ctx.services.viewer, nextFace, face);
|
||||||
}
|
}
|
||||||
|
|
@ -93,10 +93,10 @@ export default [
|
||||||
{
|
{
|
||||||
id: 'CycleFacesPrev',
|
id: 'CycleFacesPrev',
|
||||||
invoke: ctx => {
|
invoke: ctx => {
|
||||||
let face = getCurrentSelectedOrFirstFace(ctx);
|
const face = getCurrentSelectedOrFirstFace(ctx);
|
||||||
if (face) {
|
if (face) {
|
||||||
let index = face.shell.faces.indexOf(face);
|
const index = face.shell.faces.indexOf(face);
|
||||||
let prevFace = faceAt(ctx.services.cadRegistry.shells, face.shell, index - 1);
|
const prevFace = faceAt(ctx.services.cadRegistry.shells, face.shell, index - 1);
|
||||||
ctx.services.pickControl.pick(prevFace);
|
ctx.services.pickControl.pick(prevFace);
|
||||||
lookAtFace(ctx.services.viewer, prevFace, face);
|
lookAtFace(ctx.services.viewer, prevFace, face);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,15 +71,15 @@ export function createPoint0(x, y, z) {
|
||||||
// return line;
|
// return line;
|
||||||
|
|
||||||
material = new THREE.SpriteMaterial( { color: 0xffffff, fog: false } );
|
material = new THREE.SpriteMaterial( { color: 0xffffff, fog: false } );
|
||||||
let sprite = new THREE.Sprite( material );
|
const sprite = new THREE.Sprite( material );
|
||||||
sprite.position.set( x, y, z );
|
sprite.position.set( x, y, z );
|
||||||
return sprite;
|
return sprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createPoint1(x, y, z) {
|
export function createPoint1(x, y, z) {
|
||||||
let geometry = new THREE.SphereGeometry( 5, 16, 16 );
|
const geometry = new THREE.SphereGeometry( 5, 16, 16 );
|
||||||
let material = new THREE.MeshBasicMaterial( {color: 0xff0000} );
|
const material = new THREE.MeshBasicMaterial( {color: 0xff0000} );
|
||||||
let sphere = new THREE.Mesh(geometry, material);
|
const sphere = new THREE.Mesh(geometry, material);
|
||||||
sphere.position.x = x;
|
sphere.position.x = x;
|
||||||
sphere.position.y = y;
|
sphere.position.y = y;
|
||||||
sphere.position.z = z;
|
sphere.position.z = z;
|
||||||
|
|
@ -87,7 +87,7 @@ export function createPoint1(x, y, z) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createLine(a, b, color) {
|
export function createLine(a, b, color) {
|
||||||
let material = new THREE.LineBasicMaterial({
|
const material = new THREE.LineBasicMaterial({
|
||||||
color: color,
|
color: color,
|
||||||
linewidth: 1
|
linewidth: 1
|
||||||
});
|
});
|
||||||
|
|
@ -113,16 +113,16 @@ export function createSolidMaterial() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function intercept(obj, methodName, aspect) {
|
export function intercept(obj, methodName, aspect) {
|
||||||
let originFunc = obj[methodName];
|
const originFunc = obj[methodName];
|
||||||
obj[methodName] = function() {
|
obj[methodName] = function() {
|
||||||
let $this = this;
|
const $this = this;
|
||||||
aspect(function() {originFunc.apply($this, arguments)}, arguments);
|
aspect(function() {originFunc.apply($this, arguments)}, arguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fixCCW(path, normal) {
|
export function fixCCW(path, normal) {
|
||||||
let _2DTransformation = new Matrix3x4().setBasis(someBasis(path, normal)).invert();
|
const _2DTransformation = new Matrix3x4().setBasis(someBasis(path, normal)).invert();
|
||||||
let path2D = [];
|
const path2D = [];
|
||||||
for (let i = 0; i < path.length; ++i) {
|
for (let i = 0; i < path.length; ++i) {
|
||||||
path2D[i] = _2DTransformation.apply(path[i]);
|
path2D[i] = _2DTransformation.apply(path[i]);
|
||||||
}
|
}
|
||||||
|
|
@ -135,27 +135,27 @@ export function fixCCW(path, normal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function someBasis2(normal) {
|
export function someBasis2(normal) {
|
||||||
let x = normal.cross(normal.randomNonParallelVector());
|
const x = normal.cross(normal.randomNonParallelVector());
|
||||||
let y = normal.cross(x).unit();
|
const y = normal.cross(x).unit();
|
||||||
return [x, y, normal];
|
return [x, y, normal];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function someBasis(twoPointsOnPlane, normal) {
|
export function someBasis(twoPointsOnPlane, normal) {
|
||||||
let a = twoPointsOnPlane[0];
|
const a = twoPointsOnPlane[0];
|
||||||
let b = twoPointsOnPlane[1];
|
const b = twoPointsOnPlane[1];
|
||||||
|
|
||||||
let x = b.minus(a).normalize();
|
const x = b.minus(a).normalize();
|
||||||
let y = normal.cross(x).normalize();
|
const y = normal.cross(x).normalize();
|
||||||
|
|
||||||
return [x, y, normal];
|
return [x, y, normal];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function normalOfCCWSeq(ccwSequence) {
|
export function normalOfCCWSeq(ccwSequence) {
|
||||||
let a = ccwSequence[0];
|
const a = ccwSequence[0];
|
||||||
let b = ccwSequence[1];
|
const b = ccwSequence[1];
|
||||||
for (let i = 2; i < ccwSequence.length; ++i) {
|
for (let i = 2; i < ccwSequence.length; ++i) {
|
||||||
let c = ccwSequence[i];
|
const c = ccwSequence[i];
|
||||||
let normal = b.minus(a).cross(c.minus(a)).normalize();
|
const normal = b.minus(a).cross(c.minus(a)).normalize();
|
||||||
if (!equal(normal.length(), 0)) {
|
if (!equal(normal.length(), 0)) {
|
||||||
return normal;
|
return normal;
|
||||||
}
|
}
|
||||||
|
|
@ -164,37 +164,37 @@ export function normalOfCCWSeq(ccwSequence) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function normalOfCCWSeqTHREE(ccwSequence) {
|
export function normalOfCCWSeqTHREE(ccwSequence) {
|
||||||
let a = ccwSequence[0];
|
const a = ccwSequence[0];
|
||||||
let b = ccwSequence[1].clone();
|
const b = ccwSequence[1].clone();
|
||||||
let c = ccwSequence[2].clone();
|
const c = ccwSequence[2].clone();
|
||||||
|
|
||||||
return b.sub(a).cross(c.sub(a)).normalize();
|
return b.sub(a).cross(c.sub(a)).normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calculateExtrudedLid(sourcePolygon, normal, direction, expansionFactor) {
|
export function calculateExtrudedLid(sourcePolygon, normal, direction, expansionFactor) {
|
||||||
let lid = [];
|
const lid = [];
|
||||||
let length = sourcePolygon.length;
|
const length = sourcePolygon.length;
|
||||||
let work;
|
let work;
|
||||||
let si;
|
let si;
|
||||||
if (!!expansionFactor && expansionFactor != 1) {
|
if (!!expansionFactor && expansionFactor != 1) {
|
||||||
if (expansionFactor < 0.001) expansionFactor = 0.0001;
|
if (expansionFactor < 0.001) expansionFactor = 0.0001;
|
||||||
let source2d = [];
|
const source2d = [];
|
||||||
work = [];
|
work = [];
|
||||||
|
|
||||||
let _3dTr = new Matrix3x4().setBasis(someBasis2(new CSG.Vector3D(normal))); // use passed basis
|
const _3dTr = new Matrix3x4().setBasis(someBasis2(new CSG.Vector3D(normal))); // use passed basis
|
||||||
let _2dTr = _3dTr.invert();
|
const _2dTr = _3dTr.invert();
|
||||||
let sourceBBox = new BBox();
|
const sourceBBox = new BBox();
|
||||||
let workBBox = new BBox();
|
const workBBox = new BBox();
|
||||||
for (si = 0; si < length; ++si) {
|
for (si = 0; si < length; ++si) {
|
||||||
let sourcePoint = _2dTr.apply(sourcePolygon[si]);
|
const sourcePoint = _2dTr.apply(sourcePolygon[si]);
|
||||||
source2d[si] = sourcePoint;
|
source2d[si] = sourcePoint;
|
||||||
work[si] = sourcePoint.multiply(expansionFactor);
|
work[si] = sourcePoint.multiply(expansionFactor);
|
||||||
work[si].z = source2d[si].z = 0;
|
work[si].z = source2d[si].z = 0;
|
||||||
sourceBBox.checkBounds(sourcePoint.x, sourcePoint.y);
|
sourceBBox.checkBounds(sourcePoint.x, sourcePoint.y);
|
||||||
workBBox.checkBounds(work[si].x, work[si].y)
|
workBBox.checkBounds(work[si].x, work[si].y)
|
||||||
}
|
}
|
||||||
let alignVector = workBBox.center().minus(sourceBBox.center());
|
const alignVector = workBBox.center().minus(sourceBBox.center());
|
||||||
let depth = normal.dot(sourcePolygon[0]);
|
const depth = normal.dot(sourcePolygon[0]);
|
||||||
for (si = 0; si < length; ++si) {
|
for (si = 0; si < length; ++si) {
|
||||||
work[si] = work[si].minus(alignVector);
|
work[si] = work[si].minus(alignVector);
|
||||||
work[si].z = depth;
|
work[si].z = depth;
|
||||||
|
|
@ -212,14 +212,14 @@ export function calculateExtrudedLid(sourcePolygon, normal, direction, expansion
|
||||||
}
|
}
|
||||||
|
|
||||||
export function triangulate(path, normal) {
|
export function triangulate(path, normal) {
|
||||||
let _3dTransformation = new Matrix3x4().setBasis(someBasis2(normal));
|
const _3dTransformation = new Matrix3x4().setBasis(someBasis2(normal));
|
||||||
let _2dTransformation = _3dTransformation.invert();
|
const _2dTransformation = _3dTransformation.invert();
|
||||||
let i;
|
let i;
|
||||||
let shell = [];
|
const shell = [];
|
||||||
for (i = 0; i < path.length; ++i) {
|
for (i = 0; i < path.length; ++i) {
|
||||||
shell[i] = _2dTransformation.apply(path[i].pos);
|
shell[i] = _2dTransformation.apply(path[i].pos);
|
||||||
}
|
}
|
||||||
let myTriangulator = new PNLTRI.Triangulator();
|
const myTriangulator = new PNLTRI.Triangulator();
|
||||||
return myTriangulator.triangulate_polygon( [ shell ] );
|
return myTriangulator.triangulate_polygon( [ shell ] );
|
||||||
// return THREE.Shape.utils.triangulateShape( f2d.shell, f2d.holes );
|
// return THREE.Shape.utils.triangulateShape( f2d.shell, f2d.holes );
|
||||||
}
|
}
|
||||||
|
|
@ -246,7 +246,7 @@ export function Polygon(shell, holes, normal) {
|
||||||
} else {
|
} else {
|
||||||
shell = fixCCW(shell, normal);
|
shell = fixCCW(shell, normal);
|
||||||
if (holes.length > 0) {
|
if (holes.length > 0) {
|
||||||
let neg = normal.negate();
|
const neg = normal.negate();
|
||||||
for (h = 0; h < holes.length; ++h) {
|
for (h = 0; h < holes.length; ++h) {
|
||||||
holes[h] = fixCCW(holes[h], neg);
|
holes[h] = fixCCW(holes[h], neg);
|
||||||
}
|
}
|
||||||
|
|
@ -260,7 +260,7 @@ export function Polygon(shell, holes, normal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Polygon.prototype.reverse = function(triangle) {
|
Polygon.prototype.reverse = function(triangle) {
|
||||||
let first = triangle[0];
|
const first = triangle[0];
|
||||||
triangle[0] = triangle[2];
|
triangle[0] = triangle[2];
|
||||||
triangle[2] = first;
|
triangle[2] = first;
|
||||||
};
|
};
|
||||||
|
|
@ -270,12 +270,12 @@ Polygon.prototype.flip = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
Polygon.prototype.shift = function(target) {
|
Polygon.prototype.shift = function(target) {
|
||||||
let shell = [];
|
const shell = [];
|
||||||
let i;
|
let i;
|
||||||
for (i = 0; i < this.shell.length; ++i) {
|
for (i = 0; i < this.shell.length; ++i) {
|
||||||
shell[i] = this.shell[i].plus(target);
|
shell[i] = this.shell[i].plus(target);
|
||||||
}
|
}
|
||||||
let holes = [];
|
const holes = [];
|
||||||
for (let h = 0; h < this.holes.length; ++h) {
|
for (let h = 0; h < this.holes.length; ++h) {
|
||||||
holes[h] = [];
|
holes[h] = [];
|
||||||
for (i = 0; i < this.holes[h].length; ++i) {
|
for (i = 0; i < this.holes[h].length; ++i) {
|
||||||
|
|
@ -286,18 +286,18 @@ Polygon.prototype.shift = function(target) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Polygon.prototype.get2DTransformation = function() {
|
Polygon.prototype.get2DTransformation = function() {
|
||||||
let _3dTransformation = new Matrix3x4().setBasis(someBasis(this.shell, this.normal));
|
const _3dTransformation = new Matrix3x4().setBasis(someBasis(this.shell, this.normal));
|
||||||
let _2dTransformation = _3dTransformation.invert();
|
const _2dTransformation = _3dTransformation.invert();
|
||||||
return _2dTransformation;
|
return _2dTransformation;
|
||||||
};
|
};
|
||||||
|
|
||||||
Polygon.prototype.to2D = function() {
|
Polygon.prototype.to2D = function() {
|
||||||
|
|
||||||
let _2dTransformation = this.get2DTransformation();
|
const _2dTransformation = this.get2DTransformation();
|
||||||
|
|
||||||
let i, h;
|
let i, h;
|
||||||
let shell = [];
|
const shell = [];
|
||||||
let holes = [];
|
const holes = [];
|
||||||
for (i = 0; i < this.shell.length; ++i) {
|
for (i = 0; i < this.shell.length; ++i) {
|
||||||
shell[i] = _2dTransformation.apply(this.shell[i]);
|
shell[i] = _2dTransformation.apply(this.shell[i]);
|
||||||
}
|
}
|
||||||
|
|
@ -318,12 +318,12 @@ Polygon.prototype.collectPaths = function(paths) {
|
||||||
Polygon.prototype.triangulate = function() {
|
Polygon.prototype.triangulate = function() {
|
||||||
|
|
||||||
function triangulateShape( contour, holes ) {
|
function triangulateShape( contour, holes ) {
|
||||||
let myTriangulator = new PNLTRI.Triangulator();
|
const myTriangulator = new PNLTRI.Triangulator();
|
||||||
return myTriangulator.triangulate_polygon( [ contour ].concat(holes) );
|
return myTriangulator.triangulate_polygon( [ contour ].concat(holes) );
|
||||||
}
|
}
|
||||||
|
|
||||||
let i, h;
|
let i, h;
|
||||||
let f2d = this.to2D();
|
const f2d = this.to2D();
|
||||||
|
|
||||||
for (i = 0; i < f2d.shell.length; ++i) {
|
for (i = 0; i < f2d.shell.length; ++i) {
|
||||||
f2d.shell[i] = f2d.shell[i].three();
|
f2d.shell[i] = f2d.shell[i].three();
|
||||||
|
|
@ -357,8 +357,8 @@ export function Sketch() {
|
||||||
export function iteratePath(path, shift, callback) {
|
export function iteratePath(path, shift, callback) {
|
||||||
let p, q, n = path.length;
|
let p, q, n = path.length;
|
||||||
for (p = n - 1,q = 0;q < n; p = q++) {
|
for (p = n - 1,q = 0;q < n; p = q++) {
|
||||||
let ai = (p + shift) % n;
|
const ai = (p + shift) % n;
|
||||||
let bi = (q + shift) % n;
|
const bi = (q + shift) % n;
|
||||||
if (!callback(path[ai], path[bi], ai, bi, q, path)) {
|
if (!callback(path[ai], path[bi], ai, bi, q, path)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -372,7 +372,7 @@ export function addAll(arr, arrToAdd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function arrFlatten1L(arr) {
|
export function arrFlatten1L(arr) {
|
||||||
let result = [];
|
const result = [];
|
||||||
for (let i = 0; i < arr.length; i++) {
|
for (let i = 0; i < arr.length; i++) {
|
||||||
addAll(result, arr[i]);
|
addAll(result, arr[i]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export function BooleanOperation(face, solid, operand, operationType) {
|
||||||
if (solid instanceof MBrepShell) {
|
if (solid instanceof MBrepShell) {
|
||||||
const op = BoolOpMap[operationType];
|
const op = BoolOpMap[operationType];
|
||||||
result = op(solid.shell, operand);
|
result = op(solid.shell, operand);
|
||||||
for (let newFace of result.faces) {
|
for (const newFace of result.faces) {
|
||||||
if (newFace.id === face.id) {
|
if (newFace.id === face.id) {
|
||||||
newFace.id = undefined;
|
newFace.id = undefined;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
export function addModification({history, pointer}, request) {
|
export function addModification({history, pointer}, request) {
|
||||||
let changingHistory = pointer !== history.length - 1;
|
const changingHistory = pointer !== history.length - 1;
|
||||||
if (changingHistory) {
|
if (changingHistory) {
|
||||||
history = [
|
history = [
|
||||||
...history.slice(0, pointer+1),
|
...history.slice(0, pointer+1),
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ function updateCSys(csys, params, findFace) {
|
||||||
}
|
}
|
||||||
|
|
||||||
(params.rotations||[]).forEach(r => {
|
(params.rotations||[]).forEach(r => {
|
||||||
let axis = csys[r.axis.toLowerCase()];
|
const axis = csys[r.axis.toLowerCase()];
|
||||||
applyRotation(csys, csys, r.angle, axis);
|
applyRotation(csys, csys, r.angle, axis);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ function updateCSys(csys, params, findFace) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function create(params, {cadRegistry}) {
|
function create(params, {cadRegistry}) {
|
||||||
let csys = CSys.origin();
|
const csys = CSys.origin();
|
||||||
updateCSys(csys, params, cadRegistry.findFace);
|
updateCSys(csys, params, cadRegistry.findFace);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -41,7 +41,7 @@ function create(params, {cadRegistry}) {
|
||||||
|
|
||||||
function previewer(ctx, initialParams, updateParams) {
|
function previewer(ctx, initialParams, updateParams) {
|
||||||
|
|
||||||
let datum3D = new DatumObject3D(CSys.origin(), ctx.services.viewer);
|
const datum3D = new DatumObject3D(CSys.origin(), ctx.services.viewer);
|
||||||
|
|
||||||
datum3D.onMove = (begin, end, delta) => {
|
datum3D.onMove = (begin, end, delta) => {
|
||||||
updateParams(params => {
|
updateParams(params => {
|
||||||
|
|
@ -50,7 +50,7 @@ function previewer(ctx, initialParams, updateParams) {
|
||||||
let y = end.y;
|
let y = end.y;
|
||||||
let z = end.z;
|
let z = end.z;
|
||||||
if (params.originatingFace) {
|
if (params.originatingFace) {
|
||||||
let face = ctx.services.cadRegistry.findFace(params.originatingFace);
|
const face = ctx.services.cadRegistry.findFace(params.originatingFace);
|
||||||
if (face) {
|
if (face) {
|
||||||
x -= face.csys.origin.x;
|
x -= face.csys.origin.x;
|
||||||
y -= face.csys.origin.y;
|
y -= face.csys.origin.y;
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ export default class CSysObject3D extends Object3D {
|
||||||
this.sceneSetup = sceneSetup;
|
this.sceneSetup = sceneSetup;
|
||||||
|
|
||||||
function createBasisArrow(name, axis, color) {
|
function createBasisArrow(name, axis, color) {
|
||||||
let meshArrow = new MeshArrow({
|
const meshArrow = new MeshArrow({
|
||||||
dir: axis,
|
dir: axis,
|
||||||
color,
|
color,
|
||||||
length: CSYS_SIZE_MODEL,
|
length: CSYS_SIZE_MODEL,
|
||||||
|
|
@ -36,9 +36,9 @@ export default class CSysObject3D extends Object3D {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMatrix() {
|
updateMatrix() {
|
||||||
let {origin: o, x, y, z} = this.csys;
|
const {origin: o, x, y, z} = this.csys;
|
||||||
|
|
||||||
let k = viewScaleFactor(this.sceneSetup, this.csys.origin, SIZE_PX, CSYS_SIZE_MODEL);
|
const k = viewScaleFactor(this.sceneSetup, this.csys.origin, SIZE_PX, CSYS_SIZE_MODEL);
|
||||||
this.matrix.set(
|
this.matrix.set(
|
||||||
k*x.x, k*y.x, k*z.x, o.x,
|
k*x.x, k*y.x, k*z.x, o.x,
|
||||||
k*x.y, k*y.y, k*z.y, o.y,
|
k*x.y, k*y.y, k*z.y, o.y,
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ export default class DatumObject3D extends Object3D {
|
||||||
|
|
||||||
this.beingDraggedAxis = dir;
|
this.beingDraggedAxis = dir;
|
||||||
|
|
||||||
let ext = dir.multiply(this.viewer.sceneSetup.workingSphere);
|
const ext = dir.multiply(this.viewer.sceneSetup.workingSphere);
|
||||||
|
|
||||||
const material = new LineBasicMaterial({color});
|
const material = new LineBasicMaterial({color});
|
||||||
const geometry = new BufferGeometry().setFromPoints( [
|
const geometry = new BufferGeometry().setFromPoints( [
|
||||||
|
|
@ -61,7 +61,7 @@ export default class DatumObject3D extends Object3D {
|
||||||
new Vector3().copy(this.csys.origin.plus(ext))
|
new Vector3().copy(this.csys.origin.plus(ext))
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let line = new Line(geometry, material);
|
const line = new Line(geometry, material);
|
||||||
this.add(line);
|
this.add(line);
|
||||||
|
|
||||||
this.exitEditMode = () => {
|
this.exitEditMode = () => {
|
||||||
|
|
@ -96,23 +96,23 @@ export default class DatumObject3D extends Object3D {
|
||||||
|
|
||||||
dragMove({mouseEvent: e}) {
|
dragMove({mouseEvent: e}) {
|
||||||
if (this.beingDraggedAxis) {
|
if (this.beingDraggedAxis) {
|
||||||
let dir = this.beingDraggedAxis;
|
const dir = this.beingDraggedAxis;
|
||||||
|
|
||||||
let traveledX = e.offsetX - this.dragInfo.startX;
|
const traveledX = e.offsetX - this.dragInfo.startX;
|
||||||
let traveledY = e.offsetY - this.dragInfo.startY;
|
const traveledY = e.offsetY - this.dragInfo.startY;
|
||||||
|
|
||||||
let raycaster = this.viewer.sceneSetup.createRaycaster(this.dragInfo.originViewCoord.x + traveledX, this.dragInfo.originViewCoord.y + traveledY);
|
const raycaster = this.viewer.sceneSetup.createRaycaster(this.dragInfo.originViewCoord.x + traveledX, this.dragInfo.originViewCoord.y + traveledY);
|
||||||
|
|
||||||
this.csys.origin.setV(this.dragInfo.csysOrigin);
|
this.csys.origin.setV(this.dragInfo.csysOrigin);
|
||||||
|
|
||||||
//see nurbs-ext - rays intersection
|
//see nurbs-ext - rays intersection
|
||||||
let zRef = dir.cross(raycaster.ray.direction);
|
const zRef = dir.cross(raycaster.ray.direction);
|
||||||
|
|
||||||
let n2 = zRef.cross(raycaster.ray.direction)._normalize();
|
const n2 = zRef.cross(raycaster.ray.direction)._normalize();
|
||||||
|
|
||||||
let u = n2.dot(this.csys.origin.minus(raycaster.ray.origin)._negate()) / n2.dot(dir);
|
const u = n2.dot(this.csys.origin.minus(raycaster.ray.origin)._negate()) / n2.dot(dir);
|
||||||
|
|
||||||
let delta = dir.multiply(u);
|
const delta = dir.multiply(u);
|
||||||
this.csys.origin._plus(delta);
|
this.csys.origin._plus(delta);
|
||||||
|
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
|
|
@ -141,7 +141,7 @@ export default class DatumObject3D extends Object3D {
|
||||||
|
|
||||||
function addOnHoverBehaviour(handle, viewer) {
|
function addOnHoverBehaviour(handle, viewer) {
|
||||||
handle.onMouseDown = function(e) {
|
handle.onMouseDown = function(e) {
|
||||||
let datum = this.parent.parent.parent;
|
const datum = this.parent.parent.parent;
|
||||||
if (datum.freezeDragging) {
|
if (datum.freezeDragging) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -149,8 +149,8 @@ function addOnHoverBehaviour(handle, viewer) {
|
||||||
datum.dragStart(e.mouseEvent, this.parent);
|
datum.dragStart(e.mouseEvent, this.parent);
|
||||||
};
|
};
|
||||||
|
|
||||||
let defaultColor = handle.material.color.getHex();
|
const defaultColor = handle.material.color.getHex();
|
||||||
let setColor = createExpensiveSetter(color => handle.material.color.setHex(color));
|
const setColor = createExpensiveSetter(color => handle.material.color.setHex(color));
|
||||||
|
|
||||||
const handleState = createReactiveState({
|
const handleState = createReactiveState({
|
||||||
selected: null,
|
selected: null,
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ import {DatumParamsRenderer} from '../DatumParamsRenderer';
|
||||||
|
|
||||||
function move(params, {cadRegistry}) {
|
function move(params, {cadRegistry}) {
|
||||||
|
|
||||||
let mDatum = cadRegistry.findDatum(params.datum);
|
const mDatum = cadRegistry.findDatum(params.datum);
|
||||||
|
|
||||||
let csys = mDatum.csys.clone();
|
const csys = mDatum.csys.clone();
|
||||||
csys.origin.x += params.x;
|
csys.origin.x += params.x;
|
||||||
csys.origin.y += params.y;
|
csys.origin.y += params.y;
|
||||||
csys.origin.z += params.z;
|
csys.origin.z += params.z;
|
||||||
|
|
@ -24,16 +24,16 @@ function move(params, {cadRegistry}) {
|
||||||
|
|
||||||
function previewer(ctx, initialParams, updateParams) {
|
function previewer(ctx, initialParams, updateParams) {
|
||||||
|
|
||||||
let mDatum = ctx.services.cadRegistry.findDatum(initialParams.datum);
|
const mDatum = ctx.services.cadRegistry.findDatum(initialParams.datum);
|
||||||
if (!mDatum) {
|
if (!mDatum) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let view = mDatum.ext.view;
|
const view = mDatum.ext.view;
|
||||||
if (!view) {
|
if (!view) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let datum3D = view.rootGroup;
|
const datum3D = view.rootGroup;
|
||||||
datum3D.beginOperation();
|
datum3D.beginOperation();
|
||||||
datum3D.onMove = (begin, end, delta) => {
|
datum3D.onMove = (begin, end, delta) => {
|
||||||
updateParams(params => {
|
updateParams(params => {
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,11 @@ import {ORIGIN} from "math/vector";
|
||||||
|
|
||||||
function rotate(params, {cadRegistry}) {
|
function rotate(params, {cadRegistry}) {
|
||||||
|
|
||||||
let mDatum = cadRegistry.findDatum(params.datum);
|
const mDatum = cadRegistry.findDatum(params.datum);
|
||||||
|
|
||||||
let axis = mDatum.csys[params.axis.toLowerCase()];
|
const axis = mDatum.csys[params.axis.toLowerCase()];
|
||||||
|
|
||||||
let csys = mDatum.csys.clone();
|
const csys = mDatum.csys.clone();
|
||||||
|
|
||||||
applyRotation(mDatum.csys, csys, params.angle, axis);
|
applyRotation(mDatum.csys, csys, params.angle, axis);
|
||||||
|
|
||||||
|
|
@ -22,25 +22,25 @@ function rotate(params, {cadRegistry}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let auxMatrix = new Matrix3x4();
|
const auxMatrix = new Matrix3x4();
|
||||||
|
|
||||||
function previewer(ctx, initialParams) {
|
function previewer(ctx, initialParams) {
|
||||||
|
|
||||||
let mDatum = ctx.services.cadRegistry.findDatum(initialParams.datum);
|
const mDatum = ctx.services.cadRegistry.findDatum(initialParams.datum);
|
||||||
|
|
||||||
if (!mDatum) {
|
if (!mDatum) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let view = mDatum.ext.view;
|
const view = mDatum.ext.view;
|
||||||
if (!view) {
|
if (!view) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let datum3D = view.rootGroup;
|
const datum3D = view.rootGroup;
|
||||||
datum3D.beginOperation(true);
|
datum3D.beginOperation(true);
|
||||||
|
|
||||||
function update(params) {
|
function update(params) {
|
||||||
let axis = mDatum.csys[params.axis.toLowerCase()];
|
const axis = mDatum.csys[params.axis.toLowerCase()];
|
||||||
applyRotation(mDatum.csys, datum3D.csys, params.angle, axis);
|
applyRotation(mDatum.csys, datum3D.csys, params.angle, axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ export function singleShellRespone(oldShell, newShellData) {
|
||||||
throw 'operation failed';
|
throw 'operation failed';
|
||||||
}
|
}
|
||||||
|
|
||||||
let consumed = [oldShell];
|
const consumed = [oldShell];
|
||||||
let created = readShellData(newShellData, consumed, oldShell.csys);
|
const created = readShellData(newShellData, consumed, oldShell.csys);
|
||||||
return {
|
return {
|
||||||
consumed: consumed,
|
consumed: consumed,
|
||||||
created: [created]
|
created: [created]
|
||||||
|
|
@ -17,29 +17,29 @@ export function singleShellRespone(oldShell, newShellData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function readShellData(data, consumed, csys) {
|
export function readShellData(data, consumed, csys) {
|
||||||
let exposure = __CAD_APP.services.exposure;
|
const exposure = __CAD_APP.services.exposure;
|
||||||
let model = new exposure.scene.readShellEntityFromJson(data, consumed, csys);
|
const model = new exposure.scene.readShellEntityFromJson(data, consumed, csys);
|
||||||
model.brepShell.data.externals.engine = 'e0';
|
model.brepShell.data.externals.engine = 'e0';
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function managedByE0(mShell) {
|
export function managedByE0(mShell) {
|
||||||
let externals = mShell.brepShell && mShell.brepShell.data && mShell.brepShell.data.externals;
|
const externals = mShell.brepShell && mShell.brepShell.data && mShell.brepShell.data.externals;
|
||||||
return externals && externals.engine === 'e0';
|
return externals && externals.engine === 'e0';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function readSketchContour(contour, face) {
|
export function readSketchContour(contour, face) {
|
||||||
let tr = face.csys.outTransformation;
|
const tr = face.csys.outTransformation;
|
||||||
let path = [];
|
const path = [];
|
||||||
contour.segments.forEach(s => {
|
contour.segments.forEach(s => {
|
||||||
if (s.isCurve) {
|
if (s.isCurve) {
|
||||||
if (s.constructor.name === 'Circle') {
|
if (s.constructor.name === 'Circle') {
|
||||||
const dir = face.csys.z.data();
|
const dir = face.csys.z.data();
|
||||||
path.push({TYPE: PRIMITIVE_TYPES.CIRCLE, c: tr.apply(s.c).data(), dir, r: s.r});
|
path.push({TYPE: PRIMITIVE_TYPES.CIRCLE, c: tr.apply(s.c).data(), dir, r: s.r});
|
||||||
} else if (s.constructor.name === 'Arc') {
|
} else if (s.constructor.name === 'Arc') {
|
||||||
let a = s.inverted ? s.b : s.a;
|
const a = s.inverted ? s.b : s.a;
|
||||||
let b = s.inverted ? s.a : s.b;
|
const b = s.inverted ? s.a : s.b;
|
||||||
let tangent = tr._apply(s.c.minus(a))._cross(face.csys.z)._normalize();
|
const tangent = tr._apply(s.c.minus(a))._cross(face.csys.z)._normalize();
|
||||||
if (s.inverted) {
|
if (s.inverted) {
|
||||||
tangent._negate();
|
tangent._negate();
|
||||||
}
|
}
|
||||||
|
|
@ -50,7 +50,7 @@ export function readSketchContour(contour, face) {
|
||||||
tangent: tangent.data()
|
tangent: tangent.data()
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
let nurbs = s.toNurbs(face.csys).impl;
|
const nurbs = s.toNurbs(face.csys).impl;
|
||||||
path.push(Object.assign({TYPE: PRIMITIVE_TYPES.B_SPLINE}, nurbs.serialize()));
|
path.push(Object.assign({TYPE: PRIMITIVE_TYPES.B_SPLINE}, nurbs.serialize()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -67,7 +67,7 @@ export function readSketchContour(contour, face) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function readSketch(face, request, sketchStorageService) {
|
export function readSketch(face, request, sketchStorageService) {
|
||||||
let sketch = sketchStorageService.readSketch(face.id);
|
const sketch = sketchStorageService.readSketch(face.id);
|
||||||
if (!sketch) throw 'sketch not found for the face ' + face.id;
|
if (!sketch) throw 'sketch not found for the face ' + face.id;
|
||||||
return sketch.fetchContours().map(c => readSketchContour(c, face));
|
return sketch.fetchContours().map(c => readSketchContour(c, face));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
|
|
||||||
export function toCString(str) {
|
export function toCString(str) {
|
||||||
let buffer = _malloc(str.length + 1);
|
const buffer = _malloc(str.length + 1);
|
||||||
writeAsciiToMemory(str, buffer);
|
writeAsciiToMemory(str, buffer);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CallCommand(command, args) {
|
export function CallCommand(command, args) {
|
||||||
|
|
||||||
let c_strings = args.map(x => toCString(x));
|
const c_strings = args.map(x => toCString(x));
|
||||||
|
|
||||||
let c_arr = _malloc(c_strings.length * 4); // 4-bytes per pointer
|
const c_arr = _malloc(c_strings.length * 4); // 4-bytes per pointer
|
||||||
c_strings.forEach(function (x, i) {
|
c_strings.forEach(function (x, i) {
|
||||||
Module.setValue(c_arr + i * 4, x, "i32");
|
Module.setValue(c_arr + i * 4, x, "i32");
|
||||||
});
|
});
|
||||||
|
|
||||||
const commandPtr = toCString(command);
|
const commandPtr = toCString(command);
|
||||||
|
|
||||||
let rc = Module._CallCommand(commandPtr, c_strings.length, c_arr);
|
const rc = Module._CallCommand(commandPtr, c_strings.length, c_arr);
|
||||||
|
|
||||||
// c_strings.forEach(_free);
|
// c_strings.forEach(_free);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ const EXTENSIONS_STORAGE_PREFIX = `${STORAGE_GLOBAL_PREFIX}.Extensions`;
|
||||||
let extensions = [];
|
let extensions = [];
|
||||||
|
|
||||||
export function activate(ctx) {
|
export function activate(ctx) {
|
||||||
let {services} = ctx;
|
const {services} = ctx;
|
||||||
let extensionsStr = services.storage.get(EXTENSIONS_STORAGE_PREFIX);
|
const extensionsStr = services.storage.get(EXTENSIONS_STORAGE_PREFIX);
|
||||||
if (extensionsStr) {
|
if (extensionsStr) {
|
||||||
extensions = JSON.parse(extensionsStr);
|
extensions = JSON.parse(extensionsStr);
|
||||||
}
|
}
|
||||||
|
|
@ -20,7 +20,7 @@ export function activate(ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function extensionReady(id, activate) {
|
function extensionReady(id, activate) {
|
||||||
let extension = extensions.find(e => e.id === id);
|
const extension = extensions.find(e => e.id === id);
|
||||||
if (!extension) {
|
if (!extension) {
|
||||||
console.warn(`extension "${id}" not registered`);
|
console.warn(`extension "${id}" not registered`);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -31,7 +31,7 @@ export function activate(ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function allExtensionsReady() {
|
function allExtensionsReady() {
|
||||||
for (let e of extensions) {
|
for (const e of extensions) {
|
||||||
if (e.activate === NO_OP) {
|
if (e.activate === NO_OP) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -40,7 +40,7 @@ export function activate(ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function activateAllExtensions() {
|
function activateAllExtensions() {
|
||||||
for (let e of extensions) {
|
for (const e of extensions) {
|
||||||
e.activate(ctx);
|
e.activate(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -60,7 +60,7 @@ export function activate(ctx) {
|
||||||
function loadExtension({id, url}) {
|
function loadExtension({id, url}) {
|
||||||
console.info(`starting extension "${id}"...`);
|
console.info(`starting extension "${id}"...`);
|
||||||
|
|
||||||
let extensionScript = document.createElement('script');
|
const extensionScript = document.createElement('script');
|
||||||
extensionScript.setAttribute('src', url);
|
extensionScript.setAttribute('src', url);
|
||||||
document.head.appendChild(extensionScript);
|
document.head.appendChild(extensionScript);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ const WIDTH = 750;
|
||||||
const HEIGHT = 750;
|
const HEIGHT = 750;
|
||||||
|
|
||||||
function createPlane(params, services) {
|
function createPlane(params, services) {
|
||||||
let mDatum = services.cadRegistry.findDatum(params.datum);
|
const mDatum = services.cadRegistry.findDatum(params.datum);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
consumed: [mDatum],
|
consumed: [mDatum],
|
||||||
|
|
@ -19,20 +19,20 @@ function createPlane(params, services) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function previewGeomProvider(params, services) {
|
function previewGeomProvider(params, services) {
|
||||||
let mDatum = services.cadRegistry.findDatum(params.datum);
|
const mDatum = services.cadRegistry.findDatum(params.datum);
|
||||||
|
|
||||||
if (!mDatum) {
|
if (!mDatum) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let tr = mDatum.csys.outTransformation;
|
const tr = mDatum.csys.outTransformation;
|
||||||
|
|
||||||
const a = tr._apply(new Vector(0, 0, 0));
|
const a = tr._apply(new Vector(0, 0, 0));
|
||||||
const b = tr._apply(new Vector(WIDTH, 0, 0));
|
const b = tr._apply(new Vector(WIDTH, 0, 0));
|
||||||
const c = tr._apply(new Vector(WIDTH, HEIGHT, 0));
|
const c = tr._apply(new Vector(WIDTH, HEIGHT, 0));
|
||||||
const d = tr._apply(new Vector(0, HEIGHT, 0));
|
const d = tr._apply(new Vector(0, HEIGHT, 0));
|
||||||
|
|
||||||
let trs = [[a, b, c], [a, c, d]];
|
const trs = [[a, b, c], [a, c, d]];
|
||||||
return createMeshGeometry(trs);
|
return createMeshGeometry(trs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,15 +35,15 @@ function createPlane(params, {cadRegistry}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function previewGeomProvider(params, {cadRegistry}) {
|
function previewGeomProvider(params, {cadRegistry}) {
|
||||||
let plane = paramsToPlane(params, cadRegistry);
|
const plane = paramsToPlane(params, cadRegistry);
|
||||||
let tr = plane.get3DTransformation();
|
const tr = plane.get3DTransformation();
|
||||||
const w = 375, h = 375;
|
const w = 375, h = 375;
|
||||||
const a = tr._apply(new Vector(-w, -h, 0));
|
const a = tr._apply(new Vector(-w, -h, 0));
|
||||||
const b = tr._apply(new Vector( w, -h, 0));
|
const b = tr._apply(new Vector( w, -h, 0));
|
||||||
const c = tr._apply(new Vector( w, h, 0));
|
const c = tr._apply(new Vector( w, h, 0));
|
||||||
const d = tr._apply(new Vector(-w, h, 0));
|
const d = tr._apply(new Vector(-w, h, 0));
|
||||||
|
|
||||||
let trs = [[a, b, c], [a, c, d]];
|
const trs = [[a, b, c], [a, c, d]];
|
||||||
return createMeshGeometry(trs);
|
return createMeshGeometry(trs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,9 @@ import {menuAboveElementHint} from "cad/dom/menu/menuUtils";
|
||||||
export default class HistoryTimeline extends React.Component {
|
export default class HistoryTimeline extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {history, pointer, setHistoryPointer, rebuild, getOperation, inProgressOperation} = this.props;
|
const {history, pointer, setHistoryPointer, rebuild, getOperation, inProgressOperation} = this.props;
|
||||||
let scrolly;
|
let scrolly;
|
||||||
let eof = history.length-1;
|
const eof = history.length-1;
|
||||||
return <div className={cx(ls.root, ' small-typography')} ref={this.keepRef}>
|
return <div className={cx(ls.root, ' small-typography')} ref={this.keepRef}>
|
||||||
<Controls rebuild={rebuild} history={history} pointer={pointer} eoh={eof} setHistoryPointer={this.setHistoryPointerAndRequestScroll}/>
|
<Controls rebuild={rebuild} history={history} pointer={pointer} eoh={eof} setHistoryPointer={this.setHistoryPointerAndRequestScroll}/>
|
||||||
<div className={ls.scroller} onClick={e => scrolly.scrollLeft -= 60}><Fa icon='caret-left'/></div>
|
<div className={ls.scroller} onClick={e => scrolly.scrollLeft -= 60}><Fa icon='caret-left'/></div>
|
||||||
|
|
@ -65,11 +65,11 @@ export default class HistoryTimeline extends React.Component {
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
// this.scrollInProgressToVisibleRequest = false;
|
// this.scrollInProgressToVisibleRequest = false;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
let item = this.el.querySelector(`.${ls.history} .${ls.inProgress}`);
|
const item = this.el.querySelector(`.${ls.history} .${ls.inProgress}`);
|
||||||
if (item) {
|
if (item) {
|
||||||
item.scrollIntoView({behavior: "smooth", inline: "center", block: "end"});
|
item.scrollIntoView({behavior: "smooth", inline: "center", block: "end"});
|
||||||
} else {
|
} else {
|
||||||
let history = this.el.querySelector(`.${ls.history}`);
|
const history = this.el.querySelector(`.${ls.history}`);
|
||||||
history.scrollLeft = history.scrollWidth;
|
history.scrollLeft = history.scrollWidth;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -71,10 +71,10 @@ const ModelSection = decoratorChain(
|
||||||
connect((streams, props) => (streams.selection[props.type] || constant([])).map(selection => ({selection}))))
|
connect((streams, props) => (streams.selection[props.type] || constant([])).map(selection => ({selection}))))
|
||||||
( // eslint-disable-line no-unexpected-multiline
|
( // eslint-disable-line no-unexpected-multiline
|
||||||
function ModelSection({model, type, typeLabel, selection, select, ...props}) {
|
function ModelSection({model, type, typeLabel, selection, select, ...props}) {
|
||||||
let labelClasses = cx(ls.modelLabel, {
|
const labelClasses = cx(ls.modelLabel, {
|
||||||
[ls.selected]: selection.indexOf(model.id) !== -1
|
[ls.selected]: selection.indexOf(model.id) !== -1
|
||||||
});
|
});
|
||||||
let label = <span className={labelClasses}>
|
const label = <span className={labelClasses}>
|
||||||
<span onClick={select}>{typeLabel||type} {model.id}</span>
|
<span onClick={select}>{typeLabel||type} {model.id}</span>
|
||||||
</span>;
|
</span>;
|
||||||
return <Section label={label} {...props}/>;
|
return <Section label={label} {...props}/>;
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,12 @@ import decoratorChain from 'ui/decoratorChain';
|
||||||
import {EMPTY_OBJECT} from 'gems/objects';
|
import {EMPTY_OBJECT} from 'gems/objects';
|
||||||
|
|
||||||
function OperationHistory({history, pointer, setHistoryPointer, remove, getOperation}) {
|
function OperationHistory({history, pointer, setHistoryPointer, remove, getOperation}) {
|
||||||
let lastMod = history.length - 1;
|
const lastMod = history.length - 1;
|
||||||
return <Stack>
|
return <Stack>
|
||||||
|
|
||||||
{history.map(({type, params}, index) => {
|
{history.map(({type, params}, index) => {
|
||||||
|
|
||||||
let {appearance, label, paramsInfo, paramsInfoComponent: PIComp} = getOperation(type)||EMPTY_OBJECT;
|
const {appearance, label, paramsInfo, paramsInfoComponent: PIComp} = getOperation(type)||EMPTY_OBJECT;
|
||||||
return <div key={index} onClick={() => setHistoryPointer(index - 1)}
|
return <div key={index} onClick={() => setHistoryPointer(index - 1)}
|
||||||
className={cx(ls.item, pointer + 1 === index && ls.selected)}>
|
className={cx(ls.item, pointer + 1 === index && ls.selected)}>
|
||||||
{appearance && <ImgIcon url={appearance.icon32} size={16}/>}
|
{appearance && <ImgIcon url={appearance.icon32} size={16}/>}
|
||||||
|
|
|
||||||
|
|
@ -31,19 +31,19 @@ function SelectedModificationInfo({ history, index,
|
||||||
ctx.domService.viewerContainer.removeEventListener('click', clickAwayHandler);
|
ctx.domService.viewerContainer.removeEventListener('click', clickAwayHandler);
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
let m = history[index];
|
const m = history[index];
|
||||||
let visible = !!m;
|
const visible = !!m;
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let op = operationRegistry[m.type];
|
const op = operationRegistry[m.type];
|
||||||
if (!op) {
|
if (!op) {
|
||||||
console.warn('unknown operation ' + m.type);
|
console.warn('unknown operation ' + m.type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const appearance = resolveAppearance(op, m.params);
|
const appearance = resolveAppearance(op, m.params);
|
||||||
|
|
||||||
let indexNumber = index + 1;
|
const indexNumber = index + 1;
|
||||||
return <Widget visible={visible}
|
return <Widget visible={visible}
|
||||||
left={lh && lh.x}
|
left={lh && lh.x}
|
||||||
bottom={95}
|
bottom={95}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ function EntityList(props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const deselect = (entityId) => {
|
const deselect = (entityId) => {
|
||||||
let {value, onChange} = props;
|
const {value, onChange} = props;
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
onChange(produce(value, value => removeInPlace(value, entityId)));
|
onChange(produce(value, value => removeInPlace(value, entityId)));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ import initializeBySchema from '../../../schema/initializeBySchema';
|
||||||
export default class MultiEntity extends React.Component {
|
export default class MultiEntity extends React.Component {
|
||||||
|
|
||||||
selectionChanged = selection => {
|
selectionChanged = selection => {
|
||||||
let {itemField, schema, context} = this.props;
|
const {itemField, schema, context} = this.props;
|
||||||
let value = selection.map(id => {
|
const value = selection.map(id => {
|
||||||
let item = this.props.value.find(i => i[itemField] === id);
|
let item = this.props.value.find(i => i[itemField] === id);
|
||||||
if (!item) {
|
if (!item) {
|
||||||
item = initializeBySchema(schema, context);
|
item = initializeBySchema(schema, context);
|
||||||
|
|
@ -24,8 +24,8 @@ export default class MultiEntity extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
let {streams, entity} = this.props;
|
const {streams, entity} = this.props;
|
||||||
let selection$ = streams.selection[entity];
|
const selection$ = streams.selection[entity];
|
||||||
this.selectionChanged(selection$.value);
|
this.selectionChanged(selection$.value);
|
||||||
this.detacher = selection$.attach(this.selectionChanged);
|
this.detacher = selection$.attach(this.selectionChanged);
|
||||||
}
|
}
|
||||||
|
|
@ -39,7 +39,7 @@ export default class MultiEntity extends React.Component {
|
||||||
return <FormContext.Consumer>
|
return <FormContext.Consumer>
|
||||||
{
|
{
|
||||||
ctx => this.props.value.map(data => {
|
ctx => this.props.value.map(data => {
|
||||||
let subContext = {
|
const subContext = {
|
||||||
data,
|
data,
|
||||||
updateParam: (name, value) => {
|
updateParam: (name, value) => {
|
||||||
data[name] = value;
|
data[name] = value;
|
||||||
|
|
@ -47,8 +47,8 @@ export default class MultiEntity extends React.Component {
|
||||||
},
|
},
|
||||||
...ctx
|
...ctx
|
||||||
};
|
};
|
||||||
let {itemField} = this.props;
|
const {itemField} = this.props;
|
||||||
let entityId = data[itemField];
|
const entityId = data[itemField];
|
||||||
return <Stack key={entityId}>
|
return <Stack key={entityId}>
|
||||||
<div>{itemField}: {entityId}</div>
|
<div>{itemField}: {entityId}</div>
|
||||||
<FormContext.Provider value={subContext}>
|
<FormContext.Provider value={subContext}>
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ function addGlobalDebugActions({viewer, cadScene, cadRegistry}) {
|
||||||
},
|
},
|
||||||
|
|
||||||
AddPointPolygons: (polygons, color) => {
|
AddPointPolygons: (polygons, color) => {
|
||||||
for (let points of polygons) {
|
for (const points of polygons) {
|
||||||
for (let i = 0; i < points.length; i ++) {
|
for (let i = 0; i < points.length; i ++) {
|
||||||
debugGroup.add(createLine(points[i], points[(i + 1) % points.length], color));
|
debugGroup.add(createLine(points[i], points[(i + 1) % points.length], color));
|
||||||
}
|
}
|
||||||
|
|
@ -109,10 +109,10 @@ function addGlobalDebugActions({viewer, cadScene, cadRegistry}) {
|
||||||
window.__DEBUG__.AddPolyLine(points, color);
|
window.__DEBUG__.AddPolyLine(points, color);
|
||||||
},
|
},
|
||||||
AddFace: (face, color) => {
|
AddFace: (face, color) => {
|
||||||
for (let e of face.edges) __DEBUG__.AddHalfEdge(e, color);
|
for (const e of face.edges) __DEBUG__.AddHalfEdge(e, color);
|
||||||
},
|
},
|
||||||
AddLoop: (loop, color) => {
|
AddLoop: (loop, color) => {
|
||||||
for (let e of loop.halfEdges) __DEBUG__.AddHalfEdge(e, color);
|
for (const e of loop.halfEdges) __DEBUG__.AddHalfEdge(e, color);
|
||||||
},
|
},
|
||||||
AddVolume: (shell, color) => {
|
AddVolume: (shell, color) => {
|
||||||
color = color || 0xffffff;
|
color = color || 0xffffff;
|
||||||
|
|
@ -136,7 +136,7 @@ function addGlobalDebugActions({viewer, cadScene, cadRegistry}) {
|
||||||
AddWireframe: (shell, color) => {
|
AddWireframe: (shell, color) => {
|
||||||
color = color || 0xffffff;
|
color = color || 0xffffff;
|
||||||
const visited = new Set();
|
const visited = new Set();
|
||||||
for (let e of shell.edges) {
|
for (const e of shell.edges) {
|
||||||
const vertices = []
|
const vertices = []
|
||||||
vertices.push(e.halfEdge1.vertexA.point.three());
|
vertices.push(e.halfEdge1.vertexA.point.three());
|
||||||
vertices.push(e.halfEdge2.vertexA.point.three());
|
vertices.push(e.halfEdge2.vertexA.point.three());
|
||||||
|
|
@ -164,7 +164,7 @@ function addGlobalDebugActions({viewer, cadScene, cadRegistry}) {
|
||||||
__DEBUG__.AddPolyLine( curve.tessellate(undefined, scale), color);
|
__DEBUG__.AddPolyLine( curve.tessellate(undefined, scale), color);
|
||||||
},
|
},
|
||||||
AddParametricCurve: (curve, color, scale) => {
|
AddParametricCurve: (curve, color, scale) => {
|
||||||
let [uMin, uMax] = curve.domain();
|
const [uMin, uMax] = curve.domain();
|
||||||
__DEBUG__.AddPolyLine3(curveTess(curve, uMin, uMax, undefined, scale), color);
|
__DEBUG__.AddPolyLine3(curveTess(curve, uMin, uMax, undefined, scale), color);
|
||||||
},
|
},
|
||||||
AddVerbCurve: (curve, color) => {
|
AddVerbCurve: (curve, color) => {
|
||||||
|
|
@ -285,9 +285,9 @@ export function createPoint(x, y, z, color) {
|
||||||
x = x.x;
|
x = x.x;
|
||||||
}
|
}
|
||||||
color = color || 0x00ff00;
|
color = color || 0x00ff00;
|
||||||
let geometry = new THREE.SphereGeometry( 5, 16, 16 );
|
const geometry = new THREE.SphereGeometry( 5, 16, 16 );
|
||||||
let material = new THREE.MeshBasicMaterial( {color} );
|
const material = new THREE.MeshBasicMaterial( {color} );
|
||||||
let sphere = new THREE.Mesh(geometry, material);
|
const sphere = new THREE.Mesh(geometry, material);
|
||||||
sphere.position.x = x;
|
sphere.position.x = x;
|
||||||
sphere.position.y = y;
|
sphere.position.y = y;
|
||||||
sphere.position.z = z;
|
sphere.position.z = z;
|
||||||
|
|
@ -328,7 +328,7 @@ const DebugActions = [
|
||||||
listens: ctx => ctx.streams.selection.face,
|
listens: ctx => ctx.streams.selection.face,
|
||||||
update: checkForSelectedFaces(1),
|
update: checkForSelectedFaces(1),
|
||||||
invoke: ({services: {selection}}) => {
|
invoke: ({services: {selection}}) => {
|
||||||
let s = selection.face.single;
|
const s = selection.face.single;
|
||||||
console.log(JSON.stringify({
|
console.log(JSON.stringify({
|
||||||
polygons: s.csgGroup.polygons,
|
polygons: s.csgGroup.polygons,
|
||||||
basis: s._basis
|
basis: s._basis
|
||||||
|
|
@ -364,8 +364,8 @@ const DebugActions = [
|
||||||
const sketch = JSON.parse(localStorage.getItem(project.faceStorageKey(faceId)));
|
const sketch = JSON.parse(localStorage.getItem(project.faceStorageKey(faceId)));
|
||||||
const layers = sketch.layers.filter(l => l.name !== '__bounds__');
|
const layers = sketch.layers.filter(l => l.name !== '__bounds__');
|
||||||
const data = [];
|
const data = [];
|
||||||
for (let l of layers) {
|
for (const l of layers) {
|
||||||
for (let d of l.data) {
|
for (const d of l.data) {
|
||||||
data.push(d);
|
data.push(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import connect from 'ui/connect';
|
||||||
import {combine} from 'lstream';
|
import {combine} from 'lstream';
|
||||||
|
|
||||||
function ActionInfo({actionId, x, y, info, hint, hotKey}) {
|
function ActionInfo({actionId, x, y, info, hint, hotKey}) {
|
||||||
let visible = !!(actionId && (info || hint || hotKey));
|
const visible = !!(actionId && (info || hint || hotKey));
|
||||||
|
|
||||||
return <AuxWidget visible={visible}
|
return <AuxWidget visible={visible}
|
||||||
left={x} top={y} className={ls.root} zIndex={550}>
|
left={x} top={y} className={ls.root} zIndex={550}>
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ export default class FloatView extends React.Component {
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {views, getDescriptor} = this.props;
|
const {views, getDescriptor} = this.props;
|
||||||
|
|
||||||
function renderedIcon(icon) {
|
function renderedIcon(icon) {
|
||||||
if (typeof icon === 'string') {
|
if (typeof icon === 'string') {
|
||||||
|
|
@ -35,7 +35,7 @@ export default class FloatView extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
function view(id) {
|
function view(id) {
|
||||||
let {title, icon, Component} = getDescriptor(id);
|
const {title, icon, Component} = getDescriptor(id);
|
||||||
|
|
||||||
|
|
||||||
return <Folder className={ls.folder} title={<span> {renderedIcon(icon)} {title}</span>}>
|
return <Folder className={ls.folder} title={<span> {renderedIcon(icon)} {title}</span>}>
|
||||||
|
|
@ -45,7 +45,7 @@ export default class FloatView extends React.Component {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let selected = this.state.selected;
|
const selected = this.state.selected;
|
||||||
|
|
||||||
return <div className={ls.root}>
|
return <div className={ls.root}>
|
||||||
<div className={ls.tabs}>
|
<div className={ls.tabs}>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export default function PlugableControlBar() {
|
||||||
|
|
||||||
function ButtonGroup({actions}) {
|
function ButtonGroup({actions}) {
|
||||||
return actions.map(actionRef => {
|
return actions.map(actionRef => {
|
||||||
let [id, overrides] = toIdAndOverrides(actionRef);
|
const [id, overrides] = toIdAndOverrides(actionRef);
|
||||||
return <ConnectedActionButton key={id} actionId={id} {...overrides} />;
|
return <ConnectedActionButton key={id} actionId={id} {...overrides} />;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -23,14 +23,14 @@ function ButtonGroup({actions}) {
|
||||||
class ActionButton extends React.Component {
|
class ActionButton extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {label, cssIcons, icon, enabled, visible, actionId, ...props} = this.props;
|
const {label, cssIcons, icon, enabled, visible, actionId, ...props} = this.props;
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const Icon = icon ? icon : null;
|
const Icon = icon ? icon : null;
|
||||||
|
|
||||||
if (isMenuAction(actionId)) {
|
if (isMenuAction(actionId)) {
|
||||||
let onClick = props.onClick;
|
const onClick = props.onClick;
|
||||||
props.onClick = e => onClick(menuAboveElementHint(this.el));
|
props.onClick = e => onClick(menuAboveElementHint(this.el));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ export function ToolbarActionButtons({actions, showTitles, size}) {
|
||||||
<ToolbarGroup><ToolbarActionButtons actions={actionRef.slice(actionRef.length / 2, actionRef.length)} showTitles={showTitles} size={size} /></ToolbarGroup>
|
<ToolbarGroup><ToolbarActionButtons actions={actionRef.slice(actionRef.length / 2, actionRef.length)} showTitles={showTitles} size={size} /></ToolbarGroup>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
let [id, overrides] = toIdAndOverrides(actionRef);
|
const [id, overrides] = toIdAndOverrides(actionRef);
|
||||||
return <ConnectedActionButton actionId={id} key={id} size={size} {...overrides} noLabel={!showTitles}/>
|
return <ConnectedActionButton actionId={id} key={id} size={size} {...overrides} noLabel={!showTitles}/>
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -39,7 +39,7 @@ function ActionButton({label, icon, icon96, icon32, cssIcons, symbol, size = 'la
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let smallOrMedium = size === 'medium' || size === 'small';
|
const smallOrMedium = size === 'medium' || size === 'small';
|
||||||
if (icon) {
|
if (icon) {
|
||||||
const Icon = icon;
|
const Icon = icon;
|
||||||
icon = <Icon size={size}/>;
|
icon = <Icon size={size}/>;
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,11 @@ import {state} from 'lstream';
|
||||||
})
|
})
|
||||||
export default class Socket extends React.Component {
|
export default class Socket extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
let {getComponent, componentId, ...props} = this.props;
|
const {getComponent, componentId, ...props} = this.props;
|
||||||
if (!componentId) {
|
if (!componentId) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let Component = getComponent(componentId);
|
const Component = getComponent(componentId);
|
||||||
if (!Component) {
|
if (!Component) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ function ActionMenuItem({label, cssIcons, icon, icon32, icon96, enabled, hotKey,
|
||||||
renderedIcon = <Icon />;
|
renderedIcon = <Icon />;
|
||||||
} else {
|
} else {
|
||||||
if (icon32 || icon96) {
|
if (icon32 || icon96) {
|
||||||
let size = 16;
|
const size = 16;
|
||||||
renderedIcon = <Filler width={size} height='1.18em'/>;
|
renderedIcon = <Filler width={size} height='1.18em'/>;
|
||||||
style = {
|
style = {
|
||||||
backgroundImage: `url(${icon32 || icon96})`,
|
backgroundImage: `url(${icon32 || icon96})`,
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@ export function activate(ctx) {
|
||||||
};
|
};
|
||||||
|
|
||||||
function registerMenus(menus) {
|
function registerMenus(menus) {
|
||||||
let menusToAdd = [];
|
const menusToAdd = [];
|
||||||
let showMenuActions = [];
|
const showMenuActions = [];
|
||||||
menus.forEach(({id, actions, ...appearance}) => {
|
menus.forEach(({id, actions, ...appearance}) => {
|
||||||
let menuState = state({
|
const menuState = state({
|
||||||
visible: false,
|
visible: false,
|
||||||
orientationUp: false,
|
orientationUp: false,
|
||||||
x: undefined,
|
x: undefined,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
export const menuAboveElementHint = el => {
|
export const menuAboveElementHint = el => {
|
||||||
let {top, left, bottom} = el.getBoundingClientRect();
|
const {top, left, bottom} = el.getBoundingClientRect();
|
||||||
return ({
|
return ({
|
||||||
orientationUp: true,
|
orientationUp: true,
|
||||||
flatBottom: true,
|
flatBottom: true,
|
||||||
|
|
|
||||||
|
|
@ -16,15 +16,15 @@ export function activate(ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function imagePng() {
|
function imagePng() {
|
||||||
let auxVisible = ctx.services.cadScene.auxGroup.visible;
|
const auxVisible = ctx.services.cadScene.auxGroup.visible;
|
||||||
ctx.services.cadScene.auxGroup.visible = false;
|
ctx.services.cadScene.auxGroup.visible = false;
|
||||||
let renderer = ctx.services.viewer.sceneSetup.renderer;
|
const renderer = ctx.services.viewer.sceneSetup.renderer;
|
||||||
let clearAlpha = renderer.getClearAlpha();
|
const clearAlpha = renderer.getClearAlpha();
|
||||||
renderer.setClearAlpha(0);
|
renderer.setClearAlpha(0);
|
||||||
renderer.preserveDrawingBuffer = true;
|
renderer.preserveDrawingBuffer = true;
|
||||||
ctx.services.viewer.sceneSetup.render();
|
ctx.services.viewer.sceneSetup.render();
|
||||||
|
|
||||||
let link = document.getElementById("downloader");
|
const link = document.getElementById("downloader");
|
||||||
link.href = renderer.domElement.toDataURL('image/png');
|
link.href = renderer.domElement.toDataURL('image/png');
|
||||||
link.download = ctx.projectService.id + "-snapshot.png";
|
link.download = ctx.projectService.id + "-snapshot.png";
|
||||||
link.click();
|
link.click();
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ import {BundleSystem} from "bundler/bundleSystem";
|
||||||
|
|
||||||
export default function startApplication(callback) {
|
export default function startApplication(callback) {
|
||||||
|
|
||||||
let preUIBundles = [
|
const preUIBundles = [
|
||||||
LifecycleBundle,
|
LifecycleBundle,
|
||||||
ProjectBundle,
|
ProjectBundle,
|
||||||
StorageBundle,
|
StorageBundle,
|
||||||
|
|
@ -68,7 +68,7 @@ export default function startApplication(callback) {
|
||||||
ProjectManagerBundle
|
ProjectManagerBundle
|
||||||
];
|
];
|
||||||
|
|
||||||
let bundles = [
|
const bundles = [
|
||||||
DomBundle,
|
DomBundle,
|
||||||
SceneBundle,
|
SceneBundle,
|
||||||
MouseEventSystemBundle,
|
MouseEventSystemBundle,
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,9 @@ export function activate(ctx) {
|
||||||
const {services, streams} = ctx;
|
const {services, streams} = ctx;
|
||||||
|
|
||||||
streams.ui.keymap = state(DefaultKeymap);
|
streams.ui.keymap = state(DefaultKeymap);
|
||||||
let keymap = DefaultKeymap;
|
const keymap = DefaultKeymap;
|
||||||
//to attach to a dom element: Mousetrap(domElement).bind(...
|
//to attach to a dom element: Mousetrap(domElement).bind(...
|
||||||
for (let action of Object.keys(keymap)) {
|
for (const action of Object.keys(keymap)) {
|
||||||
const dataProvider = getDataProvider(action, services);
|
const dataProvider = getDataProvider(action, services);
|
||||||
Mousetrap.bind(keymap[action], () => ctx.actionService.run(action, dataProvider ? dataProvider() : undefined));
|
Mousetrap.bind(keymap[action], () => ctx.actionService.run(action, dataProvider ? dataProvider() : undefined));
|
||||||
}
|
}
|
||||||
|
|
@ -22,7 +22,7 @@ export function activate(ctx) {
|
||||||
function getDataProvider(action, services) {
|
function getDataProvider(action, services) {
|
||||||
if (isMenuAction(action)) {
|
if (isMenuAction(action)) {
|
||||||
return function() {
|
return function() {
|
||||||
let {left, top, width, height} = services.dom.viewerContainer.getBoundingClientRect();
|
const {left, top, width, height} = services.dom.viewerContainer.getBoundingClientRect();
|
||||||
return {
|
return {
|
||||||
x: left + width * 0.5,
|
x: left + width * 0.5,
|
||||||
y: top + height * 0.5,
|
y: top + height * 0.5,
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ export function sortPolygons(polygons) {
|
||||||
this.level = 0;
|
this.level = 0;
|
||||||
}
|
}
|
||||||
function contains(polygon, other) {
|
function contains(polygon, other) {
|
||||||
for (let point of other._2D) {
|
for (const point of other._2D) {
|
||||||
if (!isPointInsidePolygon(point, polygon._2D)) {
|
if (!isPointInsidePolygon(point, polygon._2D)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -39,7 +39,7 @@ export function sortPolygons(polygons) {
|
||||||
if (shells.length == 0) {
|
if (shells.length == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (let shell of shells) {
|
for (const shell of shells) {
|
||||||
shell.nesting = shell.nesting.filter(l => l.level == level + 1);
|
shell.nesting = shell.nesting.filter(l => l.level == level + 1);
|
||||||
allShells.push(shell);
|
allShells.push(shell);
|
||||||
}
|
}
|
||||||
|
|
@ -51,20 +51,20 @@ export function sortPolygons(polygons) {
|
||||||
|
|
||||||
function _pointOnLine(p, a, b) {
|
function _pointOnLine(p, a, b) {
|
||||||
|
|
||||||
let ab = a.minus(b);
|
const ab = a.minus(b);
|
||||||
let ap = a.minus(p);
|
const ap = a.minus(p);
|
||||||
|
|
||||||
let dp = ab.dot(ap);
|
const dp = ab.dot(ap);
|
||||||
|
|
||||||
let abLength = ab.length();
|
const abLength = ab.length();
|
||||||
let apLength = ap.length();
|
const apLength = ap.length();
|
||||||
|
|
||||||
return apLength > 0 && apLength < abLength && areEqual(abLength * apLength, dp, 1E-6);
|
return apLength > 0 && apLength < abLength && areEqual(abLength * apLength, dp, 1E-6);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function polygonsToSegments(polygons) {
|
export function polygonsToSegments(polygons) {
|
||||||
function selfIntersecting(a, b, c) {
|
function selfIntersecting(a, b, c) {
|
||||||
let f = _pointOnLine;
|
const f = _pointOnLine;
|
||||||
return f(c, a, b) || f(a, b, c) || f(b, c, a);
|
return f(c, a, b) || f(a, b, c) || f(b, c, a);
|
||||||
}
|
}
|
||||||
//polygons.filter(function(p) {
|
//polygons.filter(function(p) {
|
||||||
|
|
@ -76,14 +76,14 @@ export function polygonsToSegments(polygons) {
|
||||||
//continue;
|
//continue;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
let segmentsByPolygon = [];
|
const segmentsByPolygon = [];
|
||||||
for (let pi = 0; pi < polygons.length; pi++) {
|
for (let pi = 0; pi < polygons.length; pi++) {
|
||||||
let segments = [];
|
const segments = [];
|
||||||
let poly = polygons[pi];
|
const poly = polygons[pi];
|
||||||
let p, q, n = poly.vertices.length;
|
let p, q, n = poly.vertices.length;
|
||||||
for(p = n - 1, q = 0; q < n; p = q ++) {
|
for(p = n - 1, q = 0; q < n; p = q ++) {
|
||||||
let a = poly.vertices[p];
|
const a = poly.vertices[p];
|
||||||
let b = poly.vertices[q];
|
const b = poly.vertices[q];
|
||||||
segments.push([a.pos, b.pos]);
|
segments.push([a.pos, b.pos]);
|
||||||
}
|
}
|
||||||
segmentsByPolygon.push(segments);
|
segmentsByPolygon.push(segments);
|
||||||
|
|
@ -93,12 +93,12 @@ export function polygonsToSegments(polygons) {
|
||||||
|
|
||||||
export function reconstructSketchBounds(csg, face, strict) {
|
export function reconstructSketchBounds(csg, face, strict) {
|
||||||
strict = strict || false;
|
strict = strict || false;
|
||||||
let polygons = csg.toPolygons();
|
const polygons = csg.toPolygons();
|
||||||
let plane = face.csgGroup.plane;
|
const plane = face.csgGroup.plane;
|
||||||
let outerEdges = [];
|
const outerEdges = [];
|
||||||
let planePolygons = [];
|
const planePolygons = [];
|
||||||
for (let pi = 0; pi < polygons.length; pi++) {
|
for (let pi = 0; pi < polygons.length; pi++) {
|
||||||
let poly = polygons[pi];
|
const poly = polygons[pi];
|
||||||
if (equal(poly.plane.normal.dot(plane.normal), 1)) {
|
if (equal(poly.plane.normal.dot(plane.normal), 1)) {
|
||||||
if (equal(plane.w, poly.plane.w) && (!strict || !!poly.shared.__tcad && poly.shared.__tcad.faceId === face.id)) {
|
if (equal(plane.w, poly.plane.w) && (!strict || !!poly.shared.__tcad && poly.shared.__tcad.faceId === face.id)) {
|
||||||
planePolygons.push(poly);
|
planePolygons.push(poly);
|
||||||
|
|
@ -107,18 +107,18 @@ export function reconstructSketchBounds(csg, face, strict) {
|
||||||
}
|
}
|
||||||
let p, q, n = poly.vertices.length;
|
let p, q, n = poly.vertices.length;
|
||||||
for(p = n - 1, q = 0; q < n; p = q ++) {
|
for(p = n - 1, q = 0; q < n; p = q ++) {
|
||||||
let a = poly.vertices[p];
|
const a = poly.vertices[p];
|
||||||
let b = poly.vertices[q];
|
const b = poly.vertices[q];
|
||||||
let pointAOnPlane = equal(plane.signedDistanceToPoint(a.pos), 0);
|
const pointAOnPlane = equal(plane.signedDistanceToPoint(a.pos), 0);
|
||||||
if (!pointAOnPlane) continue;
|
if (!pointAOnPlane) continue;
|
||||||
let pointBOnPlane = equal(plane.signedDistanceToPoint(b.pos), 0);
|
const pointBOnPlane = equal(plane.signedDistanceToPoint(b.pos), 0);
|
||||||
if (pointBOnPlane) {
|
if (pointBOnPlane) {
|
||||||
outerEdges.push([a.pos, b.pos, poly]);
|
outerEdges.push([a.pos, b.pos, poly]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let outline = findOutline(planePolygons);
|
const outline = findOutline(planePolygons);
|
||||||
|
|
||||||
pickUpCraftInfo(outline, outerEdges);
|
pickUpCraftInfo(outline, outerEdges);
|
||||||
|
|
||||||
|
|
@ -126,11 +126,11 @@ export function reconstructSketchBounds(csg, face, strict) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function pickUpCraftInfo(outline, outerEdges) {
|
function pickUpCraftInfo(outline, outerEdges) {
|
||||||
let eq = strictEqual;
|
const eq = strictEqual;
|
||||||
for (let psi1 = 0; psi1 < outline.length; psi1++) {
|
for (let psi1 = 0; psi1 < outline.length; psi1++) {
|
||||||
let s1 = outline[psi1];
|
const s1 = outline[psi1];
|
||||||
for (let psi2 = 0; psi2 < outerEdges.length; psi2++) {
|
for (let psi2 = 0; psi2 < outerEdges.length; psi2++) {
|
||||||
let s2 = outerEdges[psi2];
|
const s2 = outerEdges[psi2];
|
||||||
if (equal(Math.abs(s1[0].minus(s1[1]).unit().dot(s2[0].minus(s2[1]).unit())), 1) &&
|
if (equal(Math.abs(s1[0].minus(s1[1]).unit().dot(s2[0].minus(s2[1]).unit())), 1) &&
|
||||||
(eq(s1[0], s2[0]) || eq(s1[1], s2[1]) || eq(s1[0], s2[1]) || eq(s1[1], s2[0]) ||
|
(eq(s1[0], s2[0]) || eq(s1[1], s2[1]) || eq(s1[0], s2[1]) || eq(s1[1], s2[0]) ||
|
||||||
_pointOnLine(s1[0], s2[0], s2[1]) || _pointOnLine(s1[1], s2[0], s2[1]))) {
|
_pointOnLine(s1[0], s2[0], s2[1]) || _pointOnLine(s1[1], s2[0], s2[1]))) {
|
||||||
|
|
@ -141,12 +141,12 @@ function pickUpCraftInfo(outline, outerEdges) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOutlineByCollision(segments, outerEdges) {
|
function getOutlineByCollision(segments, outerEdges) {
|
||||||
let eq = strictEqual;
|
const eq = strictEqual;
|
||||||
let outline = [];
|
const outline = [];
|
||||||
for (let psi1 = 0; psi1 < segments.length; psi1++) {
|
for (let psi1 = 0; psi1 < segments.length; psi1++) {
|
||||||
let s1 = segments[psi1];
|
const s1 = segments[psi1];
|
||||||
for (let psi2 = 0; psi2 < outerEdges.length; psi2++) {
|
for (let psi2 = 0; psi2 < outerEdges.length; psi2++) {
|
||||||
let s2 = outerEdges[psi2];
|
const s2 = outerEdges[psi2];
|
||||||
if (equal(Math.abs(s1[0].minus(s1[1]).unit().dot(s2[0].minus(s2[1]).unit())), 1) &&
|
if (equal(Math.abs(s1[0].minus(s1[1]).unit().dot(s2[0].minus(s2[1]).unit())), 1) &&
|
||||||
(eq(s1[0], s2[0]) || eq(s1[1], s2[1]) || eq(s1[0], s2[1]) || eq(s1[1], s2[0]) ||
|
(eq(s1[0], s2[0]) || eq(s1[1], s2[1]) || eq(s1[0], s2[1]) || eq(s1[1], s2[0]) ||
|
||||||
_pointOnLine(s1[0], s2[0], s2[1]) || _pointOnLine(s1[1], s2[0], s2[1]))) {
|
_pointOnLine(s1[0], s2[0], s2[1]) || _pointOnLine(s1[1], s2[0], s2[1]))) {
|
||||||
|
|
@ -158,7 +158,7 @@ function getOutlineByCollision(segments, outerEdges) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function findOutline (planePolygons) {
|
export function findOutline (planePolygons) {
|
||||||
let segmentsByPolygon = polygonsToSegments(planePolygons);
|
const segmentsByPolygon = polygonsToSegments(planePolygons);
|
||||||
//simplifySegments(segmentsByPolygon);
|
//simplifySegments(segmentsByPolygon);
|
||||||
let planeSegments = cad_utils.arrFlatten1L(segmentsByPolygon);
|
let planeSegments = cad_utils.arrFlatten1L(segmentsByPolygon);
|
||||||
//planeSegments = removeSharedEdges(planeSegments);
|
//planeSegments = removeSharedEdges(planeSegments);
|
||||||
|
|
@ -169,13 +169,13 @@ export function findOutline (planePolygons) {
|
||||||
|
|
||||||
function removeSharedEdges(segments) {
|
function removeSharedEdges(segments) {
|
||||||
segments = segments.slice();
|
segments = segments.slice();
|
||||||
let eq = strictEqual;
|
const eq = strictEqual;
|
||||||
for (let psi1 = 0; psi1 < segments.length; psi1++) {
|
for (let psi1 = 0; psi1 < segments.length; psi1++) {
|
||||||
let s1 = segments[psi1];
|
const s1 = segments[psi1];
|
||||||
if (s1 == null) continue;
|
if (s1 == null) continue;
|
||||||
for (let psi2 = 0; psi2 < segments.length; psi2++) {
|
for (let psi2 = 0; psi2 < segments.length; psi2++) {
|
||||||
if (psi1 === psi2) continue;
|
if (psi1 === psi2) continue;
|
||||||
let s2 = segments[psi2];
|
const s2 = segments[psi2];
|
||||||
if (s2 == null) continue;
|
if (s2 == null) continue;
|
||||||
if ((eq(s1[0], s2[0]) && eq(s1[1], s2[1]) || (eq(s1[0], s2[1]) && eq(s1[1], s2[0])))) {
|
if ((eq(s1[0], s2[0]) && eq(s1[1], s2[1]) || (eq(s1[0], s2[1]) && eq(s1[1], s2[0])))) {
|
||||||
segments[psi1] = null;
|
segments[psi1] = null;
|
||||||
|
|
@ -190,12 +190,12 @@ function simplifySegments(polygonToSegments) {
|
||||||
for (let pi1 = 0; pi1 < polygonToSegments.length; ++pi1) {
|
for (let pi1 = 0; pi1 < polygonToSegments.length; ++pi1) {
|
||||||
for (let pi2 = 0; pi2 < polygonToSegments.length; ++pi2) {
|
for (let pi2 = 0; pi2 < polygonToSegments.length; ++pi2) {
|
||||||
if (pi1 === pi2) continue;
|
if (pi1 === pi2) continue;
|
||||||
let polygon1 = polygonToSegments[pi1];
|
const polygon1 = polygonToSegments[pi1];
|
||||||
let polygon2 = polygonToSegments[pi2];
|
const polygon2 = polygonToSegments[pi2];
|
||||||
for (let si1 = 0; si1 < polygon1.length; ++si1) {
|
for (let si1 = 0; si1 < polygon1.length; ++si1) {
|
||||||
let seg1 = polygon1[si1];
|
const seg1 = polygon1[si1];
|
||||||
for (let si2 = 0; si2 < polygon2.length; ++si2) {
|
for (let si2 = 0; si2 < polygon2.length; ++si2) {
|
||||||
let point = polygon2[si2][0];
|
const point = polygon2[si2][0];
|
||||||
if (_pointOnLine(point, seg1[0], seg1[1])) {
|
if (_pointOnLine(point, seg1[0], seg1[1])) {
|
||||||
polygon1.push([point, seg1[1]]);
|
polygon1.push([point, seg1[1]]);
|
||||||
seg1[1] = point;
|
seg1[1] = point;
|
||||||
|
|
@ -208,37 +208,37 @@ function simplifySegments(polygonToSegments) {
|
||||||
|
|
||||||
function _closeFactorToLine(p, seg1, seg2) {
|
function _closeFactorToLine(p, seg1, seg2) {
|
||||||
|
|
||||||
let a = p.minus(seg1);
|
const a = p.minus(seg1);
|
||||||
let b = seg2.minus(seg1);
|
const b = seg2.minus(seg1);
|
||||||
let bn = b.unit();
|
const bn = b.unit();
|
||||||
|
|
||||||
let projLength = bn.dot(a);
|
const projLength = bn.dot(a);
|
||||||
let bx = bn.times(projLength);
|
const bx = bn.times(projLength);
|
||||||
if (!(projLength > 0 && projLength < b.length())) {
|
if (!(projLength > 0 && projLength < b.length())) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let c = a.minus(bx);
|
const c = a.minus(bx);
|
||||||
return c.length();
|
return c.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeTJoints(segments) {
|
function removeTJoints(segments) {
|
||||||
let pointIndex = HashTable.forVector3d();
|
const pointIndex = HashTable.forVector3d();
|
||||||
|
|
||||||
for (let i = 0; i < segments.length; ++i) {
|
for (let i = 0; i < segments.length; ++i) {
|
||||||
pointIndex.put(segments[i][0], 1);
|
pointIndex.put(segments[i][0], 1);
|
||||||
pointIndex.put(segments[i][1], 1);
|
pointIndex.put(segments[i][1], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let points = pointIndex.getKeys();
|
const points = pointIndex.getKeys();
|
||||||
let eq = strictEqual;
|
const eq = strictEqual;
|
||||||
for (let pi1 = 0; pi1 < points.length; ++pi1) {
|
for (let pi1 = 0; pi1 < points.length; ++pi1) {
|
||||||
let point = points[pi1];
|
const point = points[pi1];
|
||||||
let best = null, bestFactor;
|
let best = null, bestFactor;
|
||||||
for (let pi2 = 0; pi2 < segments.length; ++pi2) {
|
for (let pi2 = 0; pi2 < segments.length; ++pi2) {
|
||||||
let seg = segments[pi2];
|
const seg = segments[pi2];
|
||||||
if (eq(seg[0], point) || eq(seg[1], point)) continue;
|
if (eq(seg[0], point) || eq(seg[1], point)) continue;
|
||||||
let factor = _closeFactorToLine(point, seg[0], seg[1]);
|
const factor = _closeFactorToLine(point, seg[0], seg[1]);
|
||||||
if (factor != -1 && factor < 1E-6 && (best == null || factor < bestFactor)) {
|
if (factor != -1 && factor < 1E-6 && (best == null || factor < bestFactor)) {
|
||||||
best = seg;
|
best = seg;
|
||||||
bestFactor = factor;
|
bestFactor = factor;
|
||||||
|
|
@ -252,16 +252,16 @@ function removeTJoints(segments) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteRedundantPoints(path) {
|
function deleteRedundantPoints(path) {
|
||||||
let cleanedPath = [];
|
const cleanedPath = [];
|
||||||
//Delete redundant point
|
//Delete redundant point
|
||||||
let pathLength = path.length;
|
const pathLength = path.length;
|
||||||
let skipMode = false;
|
let skipMode = false;
|
||||||
for (let pi = 0; pi < pathLength; pi++) {
|
for (let pi = 0; pi < pathLength; pi++) {
|
||||||
let bIdx = ((pi + 1) % pathLength);
|
const bIdx = ((pi + 1) % pathLength);
|
||||||
let a = path[pi];
|
const a = path[pi];
|
||||||
let b = path[bIdx];
|
const b = path[bIdx];
|
||||||
let c = path[(pi + 2) % pathLength];
|
const c = path[(pi + 2) % pathLength];
|
||||||
let eq = areEqual;
|
const eq = areEqual;
|
||||||
if (!skipMode) cleanedPath.push(a);
|
if (!skipMode) cleanedPath.push(a);
|
||||||
skipMode = eq(a.minus(b).unit().dot(b.minus(c).unit()), 1, 1E-9);
|
skipMode = eq(a.minus(b).unit().dot(b.minus(c).unit()), 1, 1E-9);
|
||||||
}
|
}
|
||||||
|
|
@ -270,10 +270,10 @@ function deleteRedundantPoints(path) {
|
||||||
|
|
||||||
export function segmentsToPaths(segments) {
|
export function segmentsToPaths(segments) {
|
||||||
|
|
||||||
let veq = strictEqual;
|
const veq = strictEqual;
|
||||||
let paths = [];
|
const paths = [];
|
||||||
let index = HashTable.forVector3d();
|
const index = HashTable.forVector3d();
|
||||||
let csgIndex = HashTable.forEdge();
|
const csgIndex = HashTable.forEdge();
|
||||||
|
|
||||||
function indexPoint(p, edge) {
|
function indexPoint(p, edge) {
|
||||||
let edges = index.get(p);
|
let edges = index.get(p);
|
||||||
|
|
@ -285,10 +285,10 @@ export function segmentsToPaths(segments) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let si = 0; si < segments.length; si++) {
|
for (let si = 0; si < segments.length; si++) {
|
||||||
let k = segments[si];
|
const k = segments[si];
|
||||||
indexPoint(k[0], k);
|
indexPoint(k[0], k);
|
||||||
indexPoint(k[1], k);
|
indexPoint(k[1], k);
|
||||||
let csgInfo = k[2];
|
const csgInfo = k[2];
|
||||||
if (csgInfo !== undefined && csgInfo !== null) {
|
if (csgInfo !== undefined && csgInfo !== null) {
|
||||||
csgIndex.put([k[0], k[1]], csgInfo);
|
csgIndex.put([k[0], k[1]], csgInfo);
|
||||||
}
|
}
|
||||||
|
|
@ -296,10 +296,10 @@ export function segmentsToPaths(segments) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function nextPoint(p) {
|
function nextPoint(p) {
|
||||||
let edges = index.get(p);
|
const edges = index.get(p);
|
||||||
if (edges === null) return null;
|
if (edges === null) return null;
|
||||||
for (let i = 0; i < edges.length; i++) {
|
for (let i = 0; i < edges.length; i++) {
|
||||||
let edge = edges[i];
|
const edge = edges[i];
|
||||||
if (edge[3]) continue;
|
if (edge[3]) continue;
|
||||||
let res = null;
|
let res = null;
|
||||||
if (veq(p, edge[0])) res = edge[1];
|
if (veq(p, edge[0])) res = edge[1];
|
||||||
|
|
@ -314,7 +314,7 @@ export function segmentsToPaths(segments) {
|
||||||
|
|
||||||
let path;
|
let path;
|
||||||
for (let ei = 0; ei < segments.length; ei++) {
|
for (let ei = 0; ei < segments.length; ei++) {
|
||||||
let edge = segments[ei];
|
const edge = segments[ei];
|
||||||
if (edge[3]) {
|
if (edge[3]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -332,13 +332,13 @@ export function segmentsToPaths(segments) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let filteredPaths = [];
|
const filteredPaths = [];
|
||||||
for (let i = 0; i < paths.length; i++) {
|
for (let i = 0; i < paths.length; i++) {
|
||||||
path = paths[i];
|
path = paths[i];
|
||||||
|
|
||||||
//Set derived from object to be able to recunstruct
|
//Set derived from object to be able to recunstruct
|
||||||
cad_utils.iteratePath(path, 0, function (a, b) {
|
cad_utils.iteratePath(path, 0, function (a, b) {
|
||||||
let fromPolygon = csgIndex.get([a, b]);
|
const fromPolygon = csgIndex.get([a, b]);
|
||||||
if (fromPolygon !== null) {
|
if (fromPolygon !== null) {
|
||||||
if (fromPolygon.shared.__tcad.csgInfo) {
|
if (fromPolygon.shared.__tcad.csgInfo) {
|
||||||
a.sketchConnectionObject = fromPolygon.shared.__tcad.csgInfo.derivedFrom;
|
a.sketchConnectionObject = fromPolygon.shared.__tcad.csgInfo.derivedFrom;
|
||||||
|
|
@ -365,14 +365,14 @@ function _triangulateCSG(polygons) {
|
||||||
return [v.x, v.y, v.z];
|
return [v.x, v.y, v.z];
|
||||||
}
|
}
|
||||||
|
|
||||||
let triangled = [];
|
const triangled = [];
|
||||||
for (let poly of polygons) {
|
for (const poly of polygons) {
|
||||||
let vertices = Triangulate([poly.vertices.map(v => data(v.pos))], data(poly.plane.normal));
|
const vertices = Triangulate([poly.vertices.map(v => data(v.pos))], data(poly.plane.normal));
|
||||||
for (let i = 0; i < vertices.length; i += 3 ) {
|
for (let i = 0; i < vertices.length; i += 3 ) {
|
||||||
let a = csgVert(vertices[i]);
|
const a = csgVert(vertices[i]);
|
||||||
let b = csgVert(vertices[i + 1]);
|
const b = csgVert(vertices[i + 1]);
|
||||||
let c = csgVert(vertices[i + 2]);
|
const c = csgVert(vertices[i + 2]);
|
||||||
let csgPoly = new CSG.Polygon([a, b, c], poly.shared, poly.plane);
|
const csgPoly = new CSG.Polygon([a, b, c], poly.shared, poly.plane);
|
||||||
triangled.push(csgPoly);
|
triangled.push(csgPoly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -380,21 +380,21 @@ function _triangulateCSG(polygons) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function splitTwoSegments(a, b) {
|
function splitTwoSegments(a, b) {
|
||||||
let da = a[1].minus(a[0]);
|
const da = a[1].minus(a[0]);
|
||||||
let db = b[1].minus(b[0]);
|
const db = b[1].minus(b[0]);
|
||||||
let dc = b[0].minus(a[0]);
|
const dc = b[0].minus(a[0]);
|
||||||
|
|
||||||
let daXdb = da.cross(db);
|
const daXdb = da.cross(db);
|
||||||
if (Math.abs(dc.dot(daXdb)) > 1e-6) {
|
if (Math.abs(dc.dot(daXdb)) > 1e-6) {
|
||||||
// lines are not coplanar
|
// lines are not coplanar
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let veq = strictEqual;
|
const veq = strictEqual;
|
||||||
if (veq(a[0], b[0]) || veq(a[0], b[1]) || veq(a[1], b[0]) || veq(a[1], b[1])) {
|
if (veq(a[0], b[0]) || veq(a[0], b[1]) || veq(a[1], b[0]) || veq(a[1], b[1])) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let dcXdb = dc.cross(db);
|
const dcXdb = dc.cross(db);
|
||||||
|
|
||||||
function _split(s, ip) {
|
function _split(s, ip) {
|
||||||
if (s[0].equals(ip) || s[1].equals(ip)) {
|
if (s[0].equals(ip) || s[1].equals(ip)) {
|
||||||
|
|
@ -402,9 +402,9 @@ function splitTwoSegments(a, b) {
|
||||||
}
|
}
|
||||||
return [[s[0], ip, s[2]], [ip, s[1], s[2]]]
|
return [[s[0], ip, s[2]], [ip, s[1], s[2]]]
|
||||||
}
|
}
|
||||||
let s = dcXdb.dot(daXdb) / daXdb.lengthSquared();
|
const s = dcXdb.dot(daXdb) / daXdb.lengthSquared();
|
||||||
if (s > 0.0 && s < 1.0) {
|
if (s > 0.0 && s < 1.0) {
|
||||||
let ip = a[0].plus(da.times(s));
|
const ip = a[0].plus(da.times(s));
|
||||||
return {
|
return {
|
||||||
splitterParts : _split(a, ip),
|
splitterParts : _split(a, ip),
|
||||||
residual : _split(b, ip)
|
residual : _split(b, ip)
|
||||||
|
|
@ -414,14 +414,14 @@ function splitTwoSegments(a, b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function attract(vectors, precision) {
|
function attract(vectors, precision) {
|
||||||
let eq = areEqual();
|
const eq = areEqual();
|
||||||
let dist = distanceAB3;
|
const dist = distanceAB3;
|
||||||
vectors = vectors.slice();
|
vectors = vectors.slice();
|
||||||
for (let i = 0; i < vectors.length; i++) {
|
for (let i = 0; i < vectors.length; i++) {
|
||||||
let v1 = vectors[i];
|
const v1 = vectors[i];
|
||||||
if (v1 == null) continue;
|
if (v1 == null) continue;
|
||||||
for (let j = i + 1; j < vectors.length; j++) {
|
for (let j = i + 1; j < vectors.length; j++) {
|
||||||
let v2 = vectors[j];
|
const v2 = vectors[j];
|
||||||
if (v2 == null) continue;
|
if (v2 == null) continue;
|
||||||
if (dist(v1, v2) <= precision) {
|
if (dist(v1, v2) <= precision) {
|
||||||
Vector.prototype.setV.call(v2, v1);
|
Vector.prototype.setV.call(v2, v1);
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,9 @@ export class CSysPlaneSurfacePrototype extends SurfacePrototype {
|
||||||
boundTo(points2dOnSurface, minWidth, minHeight, offset) {
|
boundTo(points2dOnSurface, minWidth, minHeight, offset) {
|
||||||
|
|
||||||
if (points2dOnSurface.length === 0) {
|
if (points2dOnSurface.length === 0) {
|
||||||
let dx = this.csys.x.multiply(minWidth);
|
const dx = this.csys.x.multiply(minWidth);
|
||||||
let dy = this.csys.y.multiply(minHeight);
|
const dy = this.csys.y.multiply(minHeight);
|
||||||
let origin = this.csys.origin;
|
const origin = this.csys.origin;
|
||||||
return new BrepSurface(new NurbsSurface(verb.geom.NurbsSurface.byKnotsControlPointsWeights( 1, 1, [0,0,1,1], [0,0,1,1],
|
return new BrepSurface(new NurbsSurface(verb.geom.NurbsSurface.byKnotsControlPointsWeights( 1, 1, [0,0,1,1], [0,0,1,1],
|
||||||
[ [ origin.plus(dy).data(), origin.plus(dx)._plus(dy).data()] ,
|
[ [ origin.plus(dy).data(), origin.plus(dx)._plus(dy).data()] ,
|
||||||
[ origin.data(), origin.plus(dx ).data() ] ] )));
|
[ origin.data(), origin.plus(dx ).data() ] ] )));
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue