From 945282c92754bdd3a84495275e9376e0d40c1543 Mon Sep 17 00:00:00 2001 From: Alex McLean Date: Fri, 13 Mar 2026 16:31:56 +0000 Subject: [PATCH 1/3] add crackle operation (sorry prettier has reformatted everything) --- .../src/operations/operation_list.ts | 151 +++++++++--------- 1 file changed, 76 insertions(+), 75 deletions(-) diff --git a/packages/adacad-drafting-lib/src/operations/operation_list.ts b/packages/adacad-drafting-lib/src/operations/operation_list.ts index b18353909..f5e37510c 100644 --- a/packages/adacad-drafting-lib/src/operations/operation_list.ts +++ b/packages/adacad-drafting-lib/src/operations/operation_list.ts @@ -1,75 +1,76 @@ -export * from './analyzesystem/analyzesystem'; -export * from './apply_materials/apply_materials'; -export * from './apply_warp_materials/apply_warp_materials'; -export * from './apply_weft_materials/apply_weft_materials'; -export * from './assign_systems/assign_systems'; -export * from './atop/atop'; -export * from './_bindweftfloats/bindweftfloats'; -export * from './_bindwarpfloats/bindwarpfloats'; -export * from './bwimagemap/bwimagemap'; -export * from './chaos/chaos'; -export * from './clear/clear'; -export * from './combos/combos'; -export * from './complex_twill/complex_twill'; -export * from './crop/crop'; -export * from './cross_section_view/cross_section_view'; -export * from './cutout/cutout'; -export * from './deinterlace/deinterlace'; -export * from './diff/diff'; -export * from './directdrawdown/directdrawdown'; -export * from './drawdown/drawdown'; -export * from './_erase_blank/erase_blank'; -export * from './fill/fill'; -export * from './flip/flip'; -export * from './glitchsatin/glitchsatin'; -export * from './imagemap/imagemap'; -export * from './interlace/interlace'; -export * from './interlace_warps/interlace_warps' -export * from './invert/invert'; -export * from './join_left/join_left' -export * from './join_top/join_top' -export * from './layer/layer' -export * from './notation/notation' -export * from './direct_loom/direct_loom'; -export * from './floor_loom/floor_loom'; -export * from './material_sequence/material_sequence'; -export * from './makesymmetric/makesymmetric'; -export * from './margin/margin'; -export * from './mask/mask' -export * from './overlay/overlay'; -export * from './overlay_multiple/overlay_multiple'; -export * from './random/random' -export * from './rectangle/rectangle' -export * from './rotate/rotate'; -export * from './sample_length/sample_length'; -export * from './sample_width/sample_width'; -export * from './satin/satin'; -export * from './satinish/satinish'; -export * from './sawtooth/sawtooth'; -export * from './selector/selector'; -export * from './selvedge/selvedge'; -export * from './set_unset/set_unset' -export * from './shaded_satin/shaded_satin'; -export * from './shift/shift' -export * from './sierpinski_square/sierpinski_square' -export * from './sine/sine'; -export * from './slope/slope' -export * from './splice_in_warps/splice_in_warps' -export * from './splice_in_wefts/splice_in_wefts' -export * from './waffle/waffle' -export * from './stretch/stretch' -export * from './tabby/tabby' -export * from './tabby/tabby' -export * from './tile/tile' -export * from './trim/trim' -export * from './threading_treadling_sequence/threading_treadling_sequence' -export * from './rand_tree/rand_tree' -export * from './twill/twill' -export * from './undulatewarps/undulatewarps' -export * from './undulatewefts/undulatewefts' -export * from './undulating_twill/undulating_twill' -export * from './set_interlacement_to_unset/set_interlacement_to_unset' -export * from './waffleish/waffleish' -export * from './warp_profile/warp_profile' -export * from './weft_profile/weft_profile' -export * from './bitfield/bitfield' \ No newline at end of file +export * from "./analyzesystem/analyzesystem"; +export * from "./apply_materials/apply_materials"; +export * from "./apply_warp_materials/apply_warp_materials"; +export * from "./apply_weft_materials/apply_weft_materials"; +export * from "./assign_systems/assign_systems"; +export * from "./atop/atop"; +export * from "./_bindweftfloats/bindweftfloats"; +export * from "./_bindwarpfloats/bindwarpfloats"; +export * from "./bwimagemap/bwimagemap"; +export * from "./chaos/chaos"; +export * from "./clear/clear"; +export * from "./combos/combos"; +export * from "./complex_twill/complex_twill"; +export * from "./crop/crop"; +export * from "./cross_section_view/cross_section_view"; +export * from "./cutout/cutout"; +export * from "./deinterlace/deinterlace"; +export * from "./diff/diff"; +export * from "./directdrawdown/directdrawdown"; +export * from "./drawdown/drawdown"; +export * from "./_erase_blank/erase_blank"; +export * from "./fill/fill"; +export * from "./flip/flip"; +export * from "./glitchsatin/glitchsatin"; +export * from "./imagemap/imagemap"; +export * from "./interlace/interlace"; +export * from "./interlace_warps/interlace_warps"; +export * from "./invert/invert"; +export * from "./join_left/join_left"; +export * from "./join_top/join_top"; +export * from "./layer/layer"; +export * from "./notation/notation"; +export * from "./direct_loom/direct_loom"; +export * from "./floor_loom/floor_loom"; +export * from "./material_sequence/material_sequence"; +export * from "./makesymmetric/makesymmetric"; +export * from "./margin/margin"; +export * from "./mask/mask"; +export * from "./overlay/overlay"; +export * from "./overlay_multiple/overlay_multiple"; +export * from "./random/random"; +export * from "./rectangle/rectangle"; +export * from "./rotate/rotate"; +export * from "./sample_length/sample_length"; +export * from "./sample_width/sample_width"; +export * from "./satin/satin"; +export * from "./satinish/satinish"; +export * from "./sawtooth/sawtooth"; +export * from "./selector/selector"; +export * from "./selvedge/selvedge"; +export * from "./set_unset/set_unset"; +export * from "./shaded_satin/shaded_satin"; +export * from "./shift/shift"; +export * from "./sierpinski_square/sierpinski_square"; +export * from "./sine/sine"; +export * from "./slope/slope"; +export * from "./splice_in_warps/splice_in_warps"; +export * from "./splice_in_wefts/splice_in_wefts"; +export * from "./waffle/waffle"; +export * from "./stretch/stretch"; +export * from "./tabby/tabby"; +export * from "./tabby/tabby"; +export * from "./tile/tile"; +export * from "./trim/trim"; +export * from "./threading_treadling_sequence/threading_treadling_sequence"; +export * from "./rand_tree/rand_tree"; +export * from "./twill/twill"; +export * from "./undulatewarps/undulatewarps"; +export * from "./undulatewefts/undulatewefts"; +export * from "./undulating_twill/undulating_twill"; +export * from "./set_interlacement_to_unset/set_interlacement_to_unset"; +export * from "./waffleish/waffleish"; +export * from "./warp_profile/warp_profile"; +export * from "./weft_profile/weft_profile"; +export * from "./bitfield/bitfield"; +export * from "./crackle/crackle"; From 21a530fb2f9682499e02fa57ab45d8d6414e1c5d Mon Sep 17 00:00:00 2001 From: Alex McLean Date: Fri, 13 Mar 2026 16:32:28 +0000 Subject: [PATCH 2/3] crackle operation --- .../src/operations/crackle/crackle.ts | 200 ++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 packages/adacad-drafting-lib/src/operations/crackle/crackle.ts diff --git a/packages/adacad-drafting-lib/src/operations/crackle/crackle.ts b/packages/adacad-drafting-lib/src/operations/crackle/crackle.ts new file mode 100644 index 000000000..e07fbb0d0 --- /dev/null +++ b/packages/adacad-drafting-lib/src/operations/crackle/crackle.ts @@ -0,0 +1,200 @@ +import { + getAllDraftsAtInlet, + NumParam, + Operation, + OperationInlet, + OperationParam, + OpInput, + OpMeta, + OpParamVal, + StringParam, + BoolParam, + getOpParamValById, +} from ".."; +import { + getHeddle, + initDraftFromDrawdown, + warps, + wefts, +} from "../../draft/draft"; +import { Sequence } from "../../sequence"; +import { defaults } from "../../utils/defaults"; +import { structureOp } from "../categories"; + +const name = "crackle"; + +const meta: OpMeta = { + displayname: "crackle", + advanced: true, + categories: [structureOp], + authors: ["Alex McLean"], + desc: "Creates a 'crackle' weave structure by placing a motif along a path, connected with incidentals.", + // img: 'crackle.png' +}; + +//PARAMS +// const warps: NumParam = { +// name: "ends", +// type: "number", +// min: 1, +// max: 128, +// value: 32, +// dx: "Number of warps", +// }; + +// const wefts: NumParam = { +// name: "pics", +// type: "number", +// min: 1, +// max: 128, +// value: 32, +// dx: "Number of wefts", +// }; + +const incidentals: BoolParam = { + name: "Add incidentals", + type: "boolean", + truestate: "yes", + falsestate: "no", + value: true, + dx: "When selected, will add intermediary warps to connect discontinous picks", +}; + +const params: OperationParam[] = [incidentals]; + +const motif_inlet: OperationInlet = { + name: "motif", + type: "static", + value: null, + uses: "draft", + dx: "The motif that you want to place. Defaults to the standard crackle weave motif.", + num_drafts: 1, +}; + +const path_inlet: OperationInlet = { + name: "path", + type: "static", + value: null, + uses: "draft", + dx: "The path to place the motif along. Should have exactly one black cell per warp.", + num_drafts: 1, +}; + +const inlets = [motif_inlet, path_inlet]; + +const perform = (param_vals: Array, op_inputs: Array) => { + const motifs = getAllDraftsAtInlet(op_inputs, 0); + const paths = getAllDraftsAtInlet(op_inputs, 1); + + if (motifs.length == 0) return Promise.resolve([]); + const motif = motifs[0]; + const motif_width = warps(motif.drawdown); + const motif_height = wefts(motif.drawdown); + + if (paths.length == 0) return Promise.resolve([]); + const path = paths[0]; + const path_width = warps(path.drawdown); + const path_height = wefts(path.drawdown); + + const pattern = new Sequence.TwoD(); + + let motif_start = 0; + let motif_end = 0; + for (let my = 0; my < motif_height; ++my) { + if (getHeddle(motif.drawdown, my, 0)) { + motif_start = my; + } + if (getHeddle(motif.drawdown, my, motif_width - 1)) { + motif_end = my; + } + } + const motif_offset = motif_end - motif_start; + let last_found; + for (let px = 0; px < path_width; ++px) { + let path_pos; + for (let py = 0; py < path_height; ++py) { + const val = getHeddle(path.drawdown, py, px); + if (val) { + path_pos = py; + break; + } + } + if (path_pos !== undefined) { + for (let mx = 0; mx < motif_width; ++mx) { + const col = new Sequence.OneD(); + let found; + for (let py = 0; py < path_height; ++py) { + const mpos = (py + (path_height - path_pos)) % path_height; + let val: boolean | null = false; + if (mpos < motif_height) { + val = getHeddle(motif.drawdown, mpos, mx); + if (val) { + found = py; + } + } + col.push(val); + } + if (mx === 0 && found !== undefined && last_found !== undefined) { + console.log("incidental? now " + found + " vs " + last_found); + if (Math.abs(found - last_found) !== 1) { + const incidentals = []; + // We need one or more incidental + if (found === last_found) { + // they're the same, so add one in between + console.log("same, add one"); + incidentals.push((found + 1) % path_height); + } else if (Math.abs(found - last_found) > 1) { + console.log("add multiple, shortest path"); + const diff = (found - last_found + path_height) % path_height; + if (diff <= path_height / 2) { + // take the shortest path, up + for (let i = 1; i < diff; ++i) { + incidentals.push((last_found + i) % path_height); + } + } else { + // or down + for (let i = 1; i < path_height - diff; ++i) { + incidentals.push( + (last_found - i + path_height) % path_height + ); + } + } + } + for (let incidental of incidentals) { + const icol = new Sequence.OneD(); + + for (let i = 0; i < path_height; ++i) { + icol.push(i === incidental); + } + pattern.pushWarpSequence(icol.val()); + } + } + } + pattern.pushWarpSequence(col.val()); + last_found = found; + } + } + } + return Promise.resolve([{ draft: initDraftFromDrawdown(pattern.export()) }]); +}; + +const sizeCheck = (param_vals: Array): boolean => { + const cols: number = getOpParamValById(0, param_vals); + const rows: number = getOpParamValById(1, param_vals); + return cols * rows <= defaults.max_area ? true : false; +}; + +const generateName = (param_vals: Array): string => { + const num_up: number = getOpParamValById(0, param_vals) as number; + return num_up + "/crackle"; +}; + +export const crackle: Operation = { + name, + meta, + params, + inlets, + perform, + generateName, + sizeCheck, +}; From c526b08b6c35ce74cec191f827dd3244133000dc Mon Sep 17 00:00:00 2001 From: Alex McLean Date: Sat, 14 Mar 2026 09:25:54 +0000 Subject: [PATCH 3/3] small fixes --- .../docs/docs/reference/glossary/outlet.md | 6 ++-- projects/ui/angular.json | 29 +++++-------------- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/projects/docs/docs/reference/glossary/outlet.md b/projects/docs/docs/reference/glossary/outlet.md index b5a45403d..035efa05d 100644 --- a/projects/docs/docs/reference/glossary/outlet.md +++ b/projects/docs/docs/reference/glossary/outlet.md @@ -1,7 +1,7 @@ # Outlet -An outlet is a part of an [operation](./operation.md). Specifically, it used to form connections between nodes, such that the draft associated with the node connected to an [outlet](./outlet.md) can be used as input to this operation when it is connected to an operations [inlet](./inlet.md). Put another way, an inlet is a port that accepts input to an operation. The draft connected to the inlet is then manipulated by the operation. +An outlet is a part of an [operation](./operation.md). Specifically, it used to form connections between nodes, such that the draft associated with the node connected to an [outlet](./outlet.md) can be used as input to this operation when it is connected to an operations [inlet](./inlet.md). Put another way, an inlet is a port that accepts input to an operation. The draft connected to the inlet is then manipulated by the operation. -![file](./img/outlet_V2.png) +![file](./img/outlet_v2.png) -A single outlet can be used to connect its associated draft to multiple inputs. \ No newline at end of file +A single outlet can be used to connect its associated draft to multiple inputs. diff --git a/projects/ui/angular.json b/projects/ui/angular.json index 3e43beca6..0ba3b5bbf 100644 --- a/projects/ui/angular.json +++ b/projects/ui/angular.json @@ -22,18 +22,10 @@ }, "index": "src/index.html", "tsConfig": "src/tsconfig.app.json", - "polyfills": [ - "src/polyfills.ts" - ], - "assets": [ - "src/assets", - "src/favicon.ico" - ], - "styles": [ - "src/styles.scss" - ], - "scripts": [ - ], + "polyfills": ["src/polyfills.ts"], + "assets": ["src/assets", "src/favicon.ico"], + "styles": ["src/styles.scss"], + "scripts": [], "extractLicenses": false, "sourceMap": true, "optimization": false, @@ -56,7 +48,7 @@ "fileReplacements": [ { "replace": "src/environments/environment.ts", - "with": "src/environments/environment.prod.ts" + "with": "src/environments/environment.production.ts" } ] } @@ -88,13 +80,8 @@ "polyfills": "src/polyfills.ts", "tsConfig": "src/tsconfig.spec.json", "scripts": [], - "styles": [ - "src/styles.scss" - ], - "assets": [ - "src/assets", - "src/favicon.ico" - ] + "styles": ["src/styles.scss"], + "assets": ["src/assets", "src/favicon.ico"] } }, "deploy": { @@ -156,4 +143,4 @@ "cli": { "analytics": false } -} \ No newline at end of file +}