From 1632e8c0aeefd3e7bfa8813801d16c8ca584bcc2 Mon Sep 17 00:00:00 2001 From: Mohamed Adil Date: Mon, 18 Dec 2023 20:35:13 +0100 Subject: [PATCH] refactor with ModelToViewer component --- src/App/App.tsx | 239 +++++--------------------------- src/App/App.types.ts | 28 ++-- src/App/solveWorker.ts | 38 +---- src/App/utils/ModelToViewer.tsx | 220 +++++++++++++++++++++++++++++ 4 files changed, 277 insertions(+), 248 deletions(-) create mode 100644 src/App/utils/ModelToViewer.tsx diff --git a/src/App/App.tsx b/src/App/App.tsx index 0b0adc02..761274d5 100644 --- a/src/App/App.tsx +++ b/src/App/App.tsx @@ -1,42 +1,48 @@ -import { - Index, - Show, - batch, - createEffect, - createSignal, - on, - onMount, -} from "solid-js"; +import { batch, createEffect, createSignal, on, onMount } from "solid-js"; import { createMutable, createStore } from "solid-js/store"; import { Layouter } from "../Layouter/Layouter"; import { Editor } from "../Editor/Editor"; import { Viewer, setRenderAction } from "../Viewer/Viewer"; -import { Node } from "../Viewer/objects/Node"; -import { Text } from "../Viewer/objects/Text"; import { Grid } from "../Viewer/objects/Grid"; -import { Element } from "../Viewer/objects/Element"; -import { NodeSupport } from "../Viewer/objects/NodeSupport"; -import { NodeLoad } from "../Viewer/objects/NodeLoad"; import { Settings, SettingsType } from "../Settings/Settings"; -import { ElementResult } from "../Viewer/objects/ElementResult"; -import { NodeResult } from "../Viewer/objects/NodeResults"; import { EditorBar } from "../EditorBar/EditorBar"; import { Parameters, ParametersType } from "../Parameters/Parameters"; import { Login, supabase } from "../Login/Login"; import { Axes } from "../Viewer/objects/Axes"; import { Export } from "../Export/Export"; import { Model } from "./App.types"; -import { Report } from "../Report/Report"; +import { ModelToViewer } from "./utils/ModelToViewer"; -// todo: parse assignments and results outside solver -// todo: then isolate dynamic script loading from static -// todo: then refactor editor to be toggled through source-code menu -// refactor app to accept model and onchange +// todo: refactor App to take model, parameter, onParameterChange, settings +// todo: isolate dynamic script loading from static +// todo: refactor editor to be toggled through source-code menu type AppProps = { script?: string; }; export function App(props: AppProps) { + const settings = createMutable({ + gridSize: 25, + displayScale: 1, + nodes: true, + elements: true, + nodesIndices: false, + elementsIndices: false, + supports: true, + loads: true, + deformedShape: true, + elementResults: "none", + nodeResults: "none", + }); + const [parameters, setParameters] = createSignal({}); + const [model, setModel] = createStore({ + nodes: [], + elements: [], + assignments: [], + analysisResults: {}, + designResults: [], + }); + const solveWorker = new Worker(new URL("./solveWorker.ts", import.meta.url), { type: "module", }); @@ -71,38 +77,13 @@ export const assignments = [ ] export const analysisResults = analyze(nodes, elements, assignments);`; - const defaultSettings: SettingsType = { - gridSize: 25, - displayScale: 1, - nodes: true, - elements: true, - nodesIndices: false, - elementsIndices: false, - supports: true, - loads: true, - deformedShape: true, - elementResults: "none", - nodeResults: "none", - }; - const settings = createMutable(defaultSettings); - const [model, setModel] = createStore({ - nodes: [], - elements: [], - assignments: [], - analysisResults: {}, - designResults: [], - }); + const [script, setScript] = createSignal(""); const [currentScript, setCurrentScript] = createSignal(""); const [showSave, setShowSave] = createSignal(false); - const [deformedNodes, setDeformedNodes] = createSignal([]); - const [nodeSupports, setNodeSupports] = createSignal([]); - const [nodeLoads, setNodeLoads] = createSignal([]); - const [elementResults, setElementResults] = createSignal([]); - const [nodeResults, setNodeResults] = createSignal([]); const [error, setError] = createSignal(undefined); + const [projectId, setProjectId] = createSignal(undefined); - const [parameters, setParameters] = createSignal({}); const [awatifKey, setAwatifKey] = createSignal(""); const [userPlan, setUserPlan] = createSignal(""); @@ -158,24 +139,6 @@ export const analysisResults = analyze(nodes, elements, assignments);`; }); }); - // on setting deformedShape change: set nodes - const nodes = () => (settings.deformedShape ? deformedNodes() : model.nodes); - - // on settings.displayScale change: set displayScale - const displayScale = () => - settings.displayScale === 0 - ? 1 - : settings.displayScale > 0 - ? settings.displayScale - : -1 / settings.displayScale; - - // on script change: define saving status - createEffect( - on([currentScript, script], () => - setShowSave(currentScript() === script() ? false : true) - ) - ); - // on settings change: render the scene createEffect( on( @@ -191,26 +154,10 @@ export const analysisResults = analyze(nodes, elements, assignments);`; ) ); - // on undeformed node change: compute deformed nodes + // on script change: define saving status createEffect( - on( - () => model.nodes, - () => { - const deformation = new Map(); - if (nodeResults().length) { - nodeResults().forEach((nodeResult: any) => { - if ("deformation" in nodeResult) - deformation.set(nodeResult.node, nodeResult.deformation); - }); - } - - setDeformedNodes( - model.nodes.map((v, i) => { - const dis = deformation.get(i) || [0, 0, 0]; - return v.map((vv: any, ii: any) => vv + dis[ii]); - }) - ); - } + on([currentScript, script], () => + setShowSave(currentScript() === script() ? false : true) ) ); @@ -250,12 +197,6 @@ export const analysisResults = analyze(nodes, elements, assignments);`; designResults: e.data.designResults, }); - setNodeSupports(e.data.nodeSupports); - setNodeLoads(e.data.nodeLoads); - - setNodeResults(e.data.nodeResults); - setElementResults(e.data.elementResults); - Object.assign(settings, e.data.settings); }); } @@ -282,115 +223,7 @@ export const analysisResults = analyze(nodes, elements, assignments);`; /> - - - {(node) => ( - - )} - - - - - - {(element) => ( - - )} - - - - - - {(node, index) => ( - - )} - - - - - - {(element, index) => ( - - )} - - - - - - {(support) => ( - - )} - - - - - - {(pointLoad) => ( - - )} - - - - - - {(elementResult) => ( - - - - )} - - - - - - {(nodeResult) => ( - - - - )} - - + @@ -403,12 +236,6 @@ export const analysisResults = analyze(nodes, elements, assignments);`; /> - - {/* */} ); } - -function computeCenter(point1: number[], point2: number[]): number[] { - return point1?.map((v, i) => (v + point2[i]) * 0.5); -} diff --git a/src/App/App.types.ts b/src/App/App.types.ts index f93a75c0..d67ab2ee 100644 --- a/src/App/App.types.ts +++ b/src/App/App.types.ts @@ -6,34 +6,40 @@ export type Model = { designResults: DesignResults; }; -// nodes and elements export type Node = [number, number, number]; export type Element = [number, number]; // assignments export type Assignment = - | supportAssignment - | loadAssignment - | propertyAssignment; -type supportAssignment = { node: number; support: [boolean, boolean, boolean] }; -type loadAssignment = { node: number; load: [number, number, number] }; -type propertyAssignment = { element: number; elasticity: number; area: number }; + | SupportAssignment + | LoadAssignment + | PropertyAssignment; +export type SupportAssignment = { + node: number; + support: [boolean, boolean, boolean]; +}; +export type LoadAssignment = { node: number; load: [number, number, number] }; +export type PropertyAssignment = { + element: number; + elasticity: number; + area: number; +}; // analysis results export type AnalysisResults = Record< string, - (deformationResult | reactionResult | normalResult)[] + (DeformationResult | ReactionResult | NormalResult)[] >; -type deformationResult = { +export type DeformationResult = { node: number; deformation: [number, number, number]; }; -type reactionResult = { +export type ReactionResult = { node: number; reaction: [number, number, number]; }; -type normalResult = { +export type NormalResult = { element: number; normal: [number, number]; }; diff --git a/src/App/solveWorker.ts b/src/App/solveWorker.ts index ce7686b7..eb1d1f8f 100644 --- a/src/App/solveWorker.ts +++ b/src/App/solveWorker.ts @@ -38,39 +38,15 @@ self.onmessage = async (e) => { } } - const nodes = onChangeResults?.nodes || module?.nodes || []; - const elements = onChangeResults?.elements || module?.elements || []; - const assignments = onChangeResults?.assignments || module?.assignments || []; - const analysisResults = onChangeResults?.analysisResults || - module?.analysisResults || { default: [] }; - const designResults = - onChangeResults?.designResults || module?.designResults || []; - - const nodeSupports: any[] = []; - const nodeLoads: any[] = []; - assignments?.forEach((a: any) => { - if ("support" in a) nodeSupports.push(a); - if ("load" in a) nodeLoads.push(a); - }); - - const nodeResults: any[] = []; - const elementResults: any[] = []; - analysisResults["default"]?.forEach((a: any) => { - if ("node" in a) nodeResults.push(a); - if ("element" in a) elementResults.push(a); - }); - self.postMessage({ parameters: e.data.key ? undefined : parameters, - nodes, - elements, - assignments, - nodeSupports, - nodeLoads, - analysisResults, - nodeResults, - elementResults, - designResults, + nodes: onChangeResults?.nodes || module?.nodes || [], + elements: onChangeResults?.elements || module?.elements || [], + assignments: onChangeResults?.assignments || module?.assignments || [], + analysisResults: onChangeResults?.analysisResults || + module?.analysisResults || { default: [] }, + designResults: + onChangeResults?.designResults || module?.designResults || [], settings: module?.settings || {}, }); }; diff --git a/src/App/utils/ModelToViewer.tsx b/src/App/utils/ModelToViewer.tsx new file mode 100644 index 00000000..e64292b2 --- /dev/null +++ b/src/App/utils/ModelToViewer.tsx @@ -0,0 +1,220 @@ +import { Index, Show, createEffect, createSignal, on } from "solid-js"; +import { SettingsType } from "../../Settings/Settings"; +import { + DeformationResult, + LoadAssignment, + Model, + NormalResult, + ReactionResult, + SupportAssignment, +} from "../App.types"; +import { Node } from "../../Viewer/objects/Node"; +import { Element } from "../../Viewer/objects/Element"; +import { Text } from "../../Viewer/objects/Text"; +import { NodeSupport } from "../../Viewer/objects/NodeSupport"; +import { NodeLoad } from "../../Viewer/objects/NodeLoad"; +import { ElementResult } from "../../Viewer/objects/ElementResult"; +import { NodeResult } from "../../Viewer/objects/NodeResults"; + +type ModelToViewerProps = { + model: Model; + settings: SettingsType; +}; + +export function ModelToViewer(props: ModelToViewerProps) { + const [nodeSupports, setNodeSupports] = createSignal([]); + const [nodeLoads, setNodeLoads] = createSignal([]); + const [nodeResults, setNodeResults] = createSignal< + (DeformationResult | ReactionResult)[] + >([]); + const [elementResults, setElementResults] = createSignal([]); + + const [deformedNodes, setDeformedNodes] = createSignal([]); + + const displayScale = () => + props.settings.displayScale === 0 + ? 1 + : props.settings.displayScale > 0 + ? props.settings.displayScale + : -1 / props.settings.displayScale; + + // on setting deformedShape change: set nodes + const nodes = () => + props.settings.deformedShape ? deformedNodes() : props.model.nodes; + + // on assignments change: parse them + createEffect(() => { + // you can do better than this with stores + const nodeSupports: SupportAssignment[] = []; + const nodeLoads: LoadAssignment[] = []; + + props.model.assignments?.forEach((a) => { + if ("support" in a) nodeSupports.push(a); + if ("load" in a) nodeLoads.push(a); + }); + + setNodeSupports(nodeSupports); + setNodeLoads(nodeLoads); + }); + + // on analysis or design results change: parse them + createEffect(() => { + // you can do better than this with stores + const nodeResults: (DeformationResult | ReactionResult)[] = []; + const elementResults: NormalResult[] = []; + + props.model.analysisResults["default"]?.forEach((a) => { + if ("node" in a) nodeResults.push(a); + if ("element" in a) elementResults.push(a); + }); + + setNodeResults(nodeResults); + setElementResults(elementResults); + }); + + // on undeformed node change: compute deformed nodes + createEffect( + on( + () => props.model.nodes, + () => { + const deformation = new Map(); + if (props.model.analysisResults.length) { + props.model.analysisResults["default"].forEach((result) => { + if ("deformation" in result) + deformation.set(result.node, result.deformation); + }); + } + + setDeformedNodes( + props.model.nodes.map((v, i) => { + const dis = deformation.get(i) || [0, 0, 0]; + return v.map((vv: any, ii: any) => vv + dis[ii]); + }) + ); + } + ) + ); + + return ( + <> + + + {(node) => ( + + )} + + + + + + {(element) => ( + + )} + + + + + + {(node, index) => ( + + )} + + + + + + {(element, index) => ( + + )} + + + + + + {(support) => ( + + )} + + + + + + {(pointLoad) => ( + + )} + + + + + + {(elementResult) => ( + + + + )} + + + + + + {(nodeResult) => ( + + + + )} + + + + ); +} + +function computeCenter(point1: number[], point2: number[]): number[] { + return point1?.map((v, i) => (v + point2[i]) * 0.5); +}