import { Quaternion, Vector3 } from '../../node_modules/three/build/three.module.js';
import { BlockInstance } from '../configurator/block_instance.js';
import { Configuration } from "../configurator/configuration.js";
import { omit, checkPropTypes, unique } from '../lib.js';
import { Block } from '../package/block/block.js';
import { Connector } from '../package/connector/connector.js';
import { ConnectorType } from '../package/connector/connector_type.js';
import { ConnectionType } from '../package/connector/connection_type.js';
import { Reporter } from '../reporter/reporter.js';
import { Package } from '../package/package.js';
import { ComponentTree } from '../component/component_tree.js';
import { Component } from '../component/component.js';
import { Connectable } from '../configurator/connectable.js';
import { Connection } from '../configurator/connection.js';
import { MaterialAssignment } from '../configurator/material_assignment.js';
import { WrappedMesh } from '../package/mesh/wrapped_mesh.js';
import { MaterialSet } from '../package/material/material_set.js';
import { MaterialCategory } from '../package/material/material_category.js';
import { calculatePlacement } from '../utilities/calculatePlacement.js';
import findConnectedConnectors from '../utilities/findConnectedConnectors.js';
import { ConfigurationInfo } from '../configurator/configuration_info.js';
/** @typedef {import("../configurator/configuration.js").InsertOption} InsertOption */
/** @typedef {import("../configurator/configuration.js").ExtendOption} ExtendOption */
/** @typedef {import("../configurator/configuration.js").CutOption} CutOption */
/** @typedef {import("../configurator/configuration.js").SplitOption} SplitOption */
/**
* @param {Configuration} configuration
* @param {Object<GUID,boolean>} ignoreConnectorIds - Object where the keys are connector ids that should be ignored
* @returns {Array<ExtendOption>}
*/
const findExtendOptions = ( configuration, ignoreConnectorIds = {}) => {
const connectables = (configuration.blockInstances || []).concat(configuration.connections || []);
const extendOptions = [];
if (connectables.length === 0) {
// empty "stage" => return all blocks
for (let block of configuration.pkg.blocks || []) {
extendOptions.push({
block,
placement: {
position: new Vector3(),
quaternion: new Quaternion()
}
});
}
}
else {
for (let connectable of connectables) {
for (let connector of connectable.connectorTemplate.connectors) {
// ignore connectors that are on the ignore list
if ( ignoreConnectorIds[ connector.id ] !== undefined && ignoreConnectorIds[ connector.id ][ connectable.id ] === true ) {
continue;
}
const connection = (configuration.connections || []).find(cnn =>
(cnn.from.connectable === connectable && cnn.from.connector === connector)
||
(cnn.to.connectable === connectable && cnn.to.connector === connector)
);
if (!connection) {
const connectablePlacement = configuration.placement[connectable.id];
for (let mateConnector of connector.mate.connectors) {
extendOptions.push({
block: mateConnector.block,
connection: {
from: {
connectable,
connector
},
to: {
connectable: 'new',
connector: mateConnector
}
},
placement: {
position: connectablePlacement.position.clone().add(
connector.position.clone().applyQuaternion(connectablePlacement.quaternion)
),
quaternion: connector.quaternion.clone().multiply(connectablePlacement.quaternion)
}
});
}
}
}
}
}
return extendOptions;
}
/**
* Find insert options for a configuration
* (every connection offers a potential insert opportunity)
* @param {Configuration} configuration
* @returns {Array<InsertOption>}
*/
const findInsertOptions = configuration => {
const insertOptions = [];
for (let connectionToSplit of configuration.connections || []) {
// all connectors in the package that could possibly
// connect to the connector at the from end of this connector
const fromMates = connectionToSplit.from.connector.mate.connectors || [];
const toMates = connectionToSplit.to.connector.mate.connectors || [];
// Every potential mate for the current from-connector sits
// on a block. To identify the insert options, find the
// the other connectors on the same block that can mate with
// the current to-connector.
for (let fromMate of fromMates) {
const otherConnectorsOnBlock = fromMate.block.connectors.filter(con => con !== fromMate);
const complementingConnectors = otherConnectorsOnBlock.filter(con => toMates.indexOf(con) > -1);
for (let toMate of complementingConnectors) {
insertOptions.push({
type: 'insert',
oldConnection: connectionToSplit,
block: fromMate.block,
newConnection1: {
from: connectionToSplit.from,
to: {
connectable: 'new',
connector: fromMate
}
},
newConnection2: {
from: {
connectable: 'new',
connector: toMate
},
to: connectionToSplit.to
},
placement: configuration.placement[connectionToSplit.id]
});
}
}
}
return insertOptions;
}
// find delete options
// every block with one connection can be deleted
// as well as blocks with connectable neighbours
// currently not sure how a connection between connections
// could be removed
// PLACEMENT!!!
const findBlockInstanceOptions = configuration => {
const cutOptions = [];
const splitOptions = [];
for (let blockInstance of configuration.blockInstances || []) {
const eqBICons = blockInstance.equalConnections;
const splitOption = {
blockInstance,
oldConnections: eqBICons,
siblingChains: blockInstance.siblingChains,
placement: configuration.placement[blockInstance.id]
};
switch (eqBICons.length) {
case 0:
case 1:
const option = {
blockInstance,
oldConnections: eqBICons,
placement: configuration.placement[blockInstance.id]
};
cutOptions.push(option);
break;
case 2:
const toUnite = [
eqBICons[0].from.connectable !== blockInstance ? eqBICons[0].from : eqBICons[0].to,
eqBICons[1].from.connectable !== blockInstance ? eqBICons[1].from : eqBICons[1].to
];
if (toUnite[0].connector.mate.connectors.includes(toUnite[1].connector)) {
cutOptions.push({
blockInstance,
oldConnections: eqBICons,
newConnection: {
from: toUnite[0],
to: toUnite[1]
},
placement: configuration.placement[blockInstance.id]
});
}
splitOptions.push(splitOption);
break;
default:
splitOptions.push(splitOption);
break;
}
}
return { cutOptions, splitOptions };
}
const findReplaceOptions = configuration => {
const replaceoptions = [];
for (let blockInstance of configuration.blockInstances || []) {
}
return replaceoptions;
}
export {
findExtendOptions,
findInsertOptions,
findBlockInstanceOptions,
findReplaceOptions,
}