diff --git a/packages/adacad-drafting-lib/src/operations/interlacing_blend/interlacing_blend.ts b/packages/adacad-drafting-lib/src/operations/interlacing_blend/interlacing_blend.ts new file mode 100644 index 000000000..ad9e167fd --- /dev/null +++ b/packages/adacad-drafting-lib/src/operations/interlacing_blend/interlacing_blend.ts @@ -0,0 +1,357 @@ +import { createCell, Draft, getHeddle, initDraftFromDrawdown, updateWarpSystemsAndShuttles, updateWeftSystemsAndShuttles, warps, wefts } from "../../draft"; +import { defaults, lcm } from "../../utils"; +import { clothOp } from "../categories"; +import { getAllDraftsAtInlet, getOpParamValById, parseDraftNames } from "../operations"; +import { NumParam, OperationInlet, OpParamVal, OpInput, Operation, OpMeta, SelectParam } from "../types"; + +const name="interlacing_blend"; + +const meta: OpMeta={ + displayname:"interlacing blend", + desc:"Creates a new draft by placing draft A and draft B on either side of a blend region. The inputs are repeated to a common size, and the blend region transitions between them based on the selected direction, center, and length.", + categories:[clothOp], + advanced:true, + old_names:["interlacing blend"] +}; + +//PARAMS +const blendRegionLength: NumParam={ + name:"blend region length", + type:"number", + min:1, + max:10000, + value:10, + dx:"the length of the blend region" +}; + +const blendCenterPercent: NumParam={ + name:"blend center percent", + type:"number", + min:0, + max:100, + value:50, + dx:"the center of the blend transition as a percent from 0 to 100" +}; + +const changePatternSize: NumParam={ + name:"change pattern size", + type:"number", + min:-10000, + max:10000, + value:0, + dx:"adds to or subtracts from the common repeated pattern size" +}; + +const blendDirection: SelectParam={ + name:"blend direction", + type:"select", + value:0, + selectlist:[ + {name:"horizontal", value:0}, + {name:"vertical", value:1} + ], + dx:"controls whether the blend runs horizontally or vertically" +}; + +const params=[blendRegionLength, blendCenterPercent, changePatternSize, blendDirection]; + +//INLETS +const draft_a: OperationInlet={ + name:"a", + type:"static", + value:null, + uses:"draft", + dx:"the first draft to blend", + num_drafts:1 +}; + +const draft_b: OperationInlet={ + name:"b", + type:"static", + value:null, + uses:"draft", + dx:"the second draft to blend", + num_drafts:1 +}; + +const inlets=[draft_a, draft_b]; + +let getCommonSize=(patternAOrg:Draft, patternBOrg:Draft, patternSizeChange:number)=>{ // get the common width and height to repeat the two patterns too + let drafts = [patternAOrg, patternBOrg]; + let commonW = lcm(drafts.map(draft=>warps(draft.drawdown)).filter(size=>size>0), defaults.lcm_timeout)+patternSizeChange; + let commonH = lcm(drafts.map(draft=>wefts(draft.drawdown)).filter(size=>size>0), defaults.lcm_timeout)+patternSizeChange; + let adjustedCommonW = commonW; + let adjustedCommonH = commonH; + + if(adjustedCommonW<1)adjustedCommonW=1; + if(adjustedCommonH<1)adjustedCommonH=1; + + return {commonW:adjustedCommonW, commonH:adjustedCommonH}; +}; + +let repeatPatternToSize=(patternOrg:Draft, targetH:number, targetW:number):(boolean | null)[][]=>{ // repeat the patterns to fill the area using common width and height + let output:(boolean | null)[][]=[]; + + for(let i=0;i{ + let inputDraftA=getAllDraftsAtInlet(op_inputs, 0); + let inputDraftB=getAllDraftsAtInlet(op_inputs, 1); + let middleColumnCount=Math.floor(getOpParamValById(0, op_params)); + let blendCenterPercent=Math.floor(getOpParamValById(1, op_params)); + let changePatternSizeValue=Math.floor(getOpParamValById(2, op_params)); + let isVertical=false; + + if(getOpParamValById(3, op_params)===1){ + isVertical=true; + } + + if(inputDraftA.length===0 || inputDraftB.length===0){ + return Promise.resolve([]); + } + + let rows=0; + let cols=0; + let patternAOrg=inputDraftA[0]; + let patternBOrg=inputDraftB[0]; + let {commonW, commonH}=getCommonSize(patternAOrg, patternBOrg, changePatternSizeValue); + let patternA=repeatPatternToSize(patternAOrg, commonH, commonW); + let patternB=repeatPatternToSize(patternBOrg, commonH, commonW); + + if(!isVertical){ + rows=commonH; + cols=commonW+commonW+middleColumnCount; + }else{ + rows=commonH+commonH+middleColumnCount; + cols=commonW; + } + + let horizontalPatternBStart=cols-commonW; + let horizontalMiddleLength=horizontalPatternBStart-commonW; + let verticalPatternBStart=rows-commonH; + let verticalMiddleLength=verticalPatternBStart-commonH; + + let drawdown:any[][]=[]; + for(let i=0;i0){ + center=(blendCenterPercent/100)*(fullTileCount-1); // find center of blend using blend center percent + } + + for(let i=0;i=horizontalPatternBStart){ // right pattern + let patternBCol=j-horizontalPatternBStart; + cellValue=patternB[i][patternBCol]; + } + else if(j>=commonW && j=remainderStart && middleColcenter; + let stripeSpacing=2+distance; // minimum distance of 2 + let useOpposite=((colInTile+1)%stripeSpacing===0); // if remainder is 0 after dividing by stripe space then flips to other pattern + // farther from center less likely to flip (ex. closer to A it can go A/A/A/B/A) + if(!isPatternASide && !isPatternBSide){ + usePatternA=(colInTile%2===0); + }else if(isPatternASide){ + usePatternA=!useOpposite; + }else{ + usePatternA=useOpposite; + } + + if(usePatternA){ // get cell values for middle region + cellValue=patternA[i][colInTile]; + }else{ + cellValue=patternB[i][colInTile]; + } + } + + if(middleCol>=remainderStart && middleCol0){ + center=(blendCenterPercent/100)*(fullTileCount-1); + } + + for(let i=0;i=verticalPatternBStart){ + let patternBRow=j-verticalPatternBStart; + cellValue=patternB[patternBRow][i]; + }else if(j>=commonH && j=remainderStart && middleColcenter; + let stripeSpacing=2+distance; + let useOpposite=((colInTile+1)%stripeSpacing===0); + + if(!isPatternASide && !isPatternBSide){ + usePatternA=(colInTile%2===0); + }else if(isPatternASide){ + usePatternA=!useOpposite; + }else{ + usePatternA=useOpposite; + } + + if(usePatternA){ + cellValue=patternA[colInTile][i]; + }else{ + cellValue=patternB[colInTile][i]; + } + } + + if(middleCol>=remainderStart && middleCol{ + let draftAInputs=getAllDraftsAtInlet(op_inputs, 0); + let draftBInputs=getAllDraftsAtInlet(op_inputs, 1); + let drafts=draftAInputs.concat(draftBInputs); + let name_list=parseDraftNames(drafts); + return "interlacing blend test(" + name_list + ")"; +}; + +let sizeCheck=(op_params:OpParamVal[], op_inputs:OpInput[]):boolean=>{ + + let inputDraftA=getAllDraftsAtInlet(op_inputs, 0); + let inputDraftB=getAllDraftsAtInlet(op_inputs, 1); + let middleColumnCount=Math.floor(getOpParamValById(0, op_params)); + let changePatternSizeValue=Math.floor(getOpParamValById(2, op_params)); + let isVertical=false; + + if(getOpParamValById(3, op_params)===1){ + isVertical=true; + } + + if(inputDraftA.length===0 || inputDraftB.length===0){ + return true; + } + + let totalRows=0; + let totalCols=0; + let patternAOrg=inputDraftA[0]; + let patternBOrg=inputDraftB[0]; + let {commonW, commonH}=getCommonSize(patternAOrg, patternBOrg, changePatternSizeValue); + + if(!isVertical){ + totalRows=commonH; + totalCols=commonW+commonW+middleColumnCount; + }else{ + totalRows=commonH+commonH+middleColumnCount; + totalCols=commonW; + } + + if(getOpParamValById(3, op_params)===1){ + isVertical=true; + } + + return totalRows*totalCols<=defaults.max_area; +}; + +export const interlacing_blend: Operation={ name, meta, params, inlets, perform, generateName, sizeCheck }; diff --git a/packages/adacad-drafting-lib/src/operations/operation_list.ts b/packages/adacad-drafting-lib/src/operations/operation_list.ts index b18353909..c840ea7f6 100644 --- a/packages/adacad-drafting-lib/src/operations/operation_list.ts +++ b/packages/adacad-drafting-lib/src/operations/operation_list.ts @@ -25,6 +25,7 @@ export * from './glitchsatin/glitchsatin'; export * from './imagemap/imagemap'; export * from './interlace/interlace'; export * from './interlace_warps/interlace_warps' +export * from './interlacing_blend/interlacing_blend'; export * from './invert/invert'; export * from './join_left/join_left' export * from './join_top/join_top' diff --git a/projects/docs/docs/reference/operations/cloth/interlacing_blend/index.md b/projects/docs/docs/reference/operations/cloth/interlacing_blend/index.md new file mode 100644 index 000000000..1a03b581d --- /dev/null +++ b/projects/docs/docs/reference/operations/cloth/interlacing_blend/index.md @@ -0,0 +1,31 @@ +--- +title: interlacing blend +sidebar_label: interlacing blend +sidebar_class_name: cloth opItem +editUrl: 'https://github.com/UnstableDesign/AdaCAD/tree/main/packages/adacad-drafting-lib/src/operations/interlacing_blend/interlacing_blend.ts' +--- + +import {OperationHeader} from '@site/src/components/OperationPage'; + + + + +## Parameters +- `blend-region-length`: the length of the blend region +- `blend center percent`: the center of the blend transition as a percent from 0 to 100 +- `change pattern size`: adds or subtracts from the common repeated pattern size +- `blend direction`: controls whether the blend runs horizontally or vertically + +## Inlets +- `draft-a`: the first draft to blend +- `draft-b`: the second draft to blend + + +## Application +Can be used to create a transition vertically or horizontally between patterns through interlacement. Create the look of a blend/gradient. + +## Developer +adacad id: `interlacing blend` + +```ts reference +https://github.com/UnstableDesign/AdaCAD/tree/main/packages/adacad-drafting-lib/src/operations/interlacing_blend/interlacing_blend.ts \ No newline at end of file diff --git a/projects/docs/docs/reference/operations/cloth/interlacing_blend/interlacing_blend.ada b/projects/docs/docs/reference/operations/cloth/interlacing_blend/interlacing_blend.ada new file mode 100644 index 000000000..f427a9029 --- /dev/null +++ b/projects/docs/docs/reference/operations/cloth/interlacing_blend/interlacing_blend.ada @@ -0,0 +1 @@ +{"version":"5.0.7","workspace":{"min_frames":8,"min_treadles":8,"type":"jacquard","epi":12,"ppi":12,"units":"in","show_materials":true,"black_cell_up":true,"number_threading":false,"selected_origin_option":3,"file_favorites":[],"hide_mixer_drafts":false,"show_advanced_operations":true,"oversize_dim_threshold":2500,"max_draft_input_area":6250000},"type":"mixer","zoom":{"editor":0.303,"mixer":0.177},"nodes":[{"node_id":30582212,"type":"op","topleft":{"x":564.4651162790699,"y":1548.046511627907}},{"node_id":61924379,"type":"op","topleft":{"x":1852.139534883721,"y":358.13953488372096}},{"node_id":38189780,"type":"draft","topleft":{"x":0,"y":0}},{"node_id":50772489,"type":"cxn","topleft":{"x":0,"y":0}},{"node_id":20561588,"type":"cxn","topleft":{"x":0,"y":0}},{"node_id":52502654,"type":"op","topleft":{"x":625.7796610169493,"y":282.4519774011299}},{"node_id":70158734,"type":"draft","topleft":{"x":0,"y":0}},{"node_id":86953434,"type":"cxn","topleft":{"x":0,"y":0}},{"node_id":46686591,"type":"cxn","topleft":{"x":0,"y":0}},{"node_id":58948118,"type":"draft","topleft":{"x":0,"y":0}},{"node_id":83515784,"type":"cxn","topleft":{"x":0,"y":0}},{"node_id":20118245,"type":"op","topleft":{"x":114.65536723163848,"y":2694.4915254237285}},{"node_id":13402403,"type":"draft","topleft":{"x":0,"y":0}},{"node_id":58302661,"type":"cxn","topleft":{"x":0,"y":0}},{"node_id":68760579,"type":"op","topleft":{"x":1210.1807909604518,"y":2691.751412429379}},{"node_id":63150322,"type":"draft","topleft":{"x":0,"y":0}},{"node_id":86602797,"type":"cxn","topleft":{"x":0,"y":0}},{"node_id":61422204,"type":"op","topleft":{"x":582.954802259887,"y":3993.983050847458}},{"node_id":64370536,"type":"draft","topleft":{"x":0,"y":0}},{"node_id":85755201,"type":"cxn","topleft":{"x":0,"y":0}},{"node_id":73950262,"type":"cxn","topleft":{"x":0,"y":0}},{"node_id":20421290,"type":"cxn","topleft":{"x":0,"y":0}}],"tree":[{"node":30582212,"parent":-1,"inputs":[{"tn":20561588,"ndx":1},{"tn":46686591,"ndx":0}],"outputs":[{"tn":83515784,"ndx":0}]},{"node":61924379,"parent":-1,"inputs":[],"outputs":[{"tn":50772489,"ndx":0}]},{"node":38189780,"parent":61924379,"inputs":[{"tn":50772489,"ndx":0}],"outputs":[{"tn":20561588,"ndx":0}]},{"node":50772489,"parent":-1,"inputs":[{"tn":61924379,"ndx":0}],"outputs":[{"tn":38189780,"ndx":0}]},{"node":20561588,"parent":-1,"inputs":[{"tn":38189780,"ndx":0}],"outputs":[{"tn":30582212,"ndx":0}]},{"node":52502654,"parent":-1,"inputs":[],"outputs":[{"tn":86953434,"ndx":0}]},{"node":70158734,"parent":52502654,"inputs":[{"tn":86953434,"ndx":0}],"outputs":[{"tn":46686591,"ndx":0}]},{"node":86953434,"parent":-1,"inputs":[{"tn":52502654,"ndx":0}],"outputs":[{"tn":70158734,"ndx":0}]},{"node":46686591,"parent":-1,"inputs":[{"tn":70158734,"ndx":0}],"outputs":[{"tn":30582212,"ndx":0}]},{"node":58948118,"parent":30582212,"inputs":[{"tn":83515784,"ndx":0}],"outputs":[]},{"node":83515784,"parent":-1,"inputs":[{"tn":30582212,"ndx":0}],"outputs":[{"tn":58948118,"ndx":0}]},{"node":20118245,"parent":-1,"inputs":[],"outputs":[{"tn":58302661,"ndx":0}]},{"node":13402403,"parent":20118245,"inputs":[{"tn":58302661,"ndx":0}],"outputs":[{"tn":73950262,"ndx":0}]},{"node":58302661,"parent":-1,"inputs":[{"tn":20118245,"ndx":0}],"outputs":[{"tn":13402403,"ndx":0}]},{"node":68760579,"parent":-1,"inputs":[],"outputs":[{"tn":86602797,"ndx":0}]},{"node":63150322,"parent":68760579,"inputs":[{"tn":86602797,"ndx":0}],"outputs":[{"tn":20421290,"ndx":0}]},{"node":86602797,"parent":-1,"inputs":[{"tn":68760579,"ndx":0}],"outputs":[{"tn":63150322,"ndx":0}]},{"node":61422204,"parent":-1,"inputs":[{"tn":73950262,"ndx":0},{"tn":20421290,"ndx":1}],"outputs":[{"tn":85755201,"ndx":0}]},{"node":64370536,"parent":61422204,"inputs":[{"tn":85755201,"ndx":0}],"outputs":[]},{"node":85755201,"parent":-1,"inputs":[{"tn":61422204,"ndx":0}],"outputs":[{"tn":64370536,"ndx":0}]},{"node":73950262,"parent":-1,"inputs":[{"tn":13402403,"ndx":0}],"outputs":[{"tn":61422204,"ndx":0}]},{"node":20421290,"parent":-1,"inputs":[{"tn":63150322,"ndx":0}],"outputs":[{"tn":61422204,"ndx":0}]}],"draft_nodes":[{"node_id":38189780,"draft_id":38189780,"ud_name":"","gen_name":"twill(3,3,Z)","notes":"","draft":null,"compressed_draft":null,"draft_visible":true,"loom":null,"loom_settings":{"type":"jacquard","epi":12,"ppi":12,"units":"in","frames":8,"treadles":8},"render_colors":true,"scale":1},{"node_id":70158734,"draft_id":70158734,"ud_name":"","gen_name":"tabby(3,3,3,3)","notes":"","draft":null,"compressed_draft":null,"draft_visible":true,"loom":null,"loom_settings":{"type":"jacquard","epi":12,"ppi":12,"units":"in","frames":8,"treadles":8},"render_colors":true,"scale":1},{"node_id":58948118,"draft_id":58948118,"ud_name":"","gen_name":"interlacing blend test(tabby(3,3,3,3)+twill(3,3,Z))","notes":"","draft":null,"compressed_draft":null,"draft_visible":true,"loom":null,"loom_settings":{"type":"jacquard","epi":12,"ppi":12,"units":"in","frames":8,"treadles":8},"render_colors":true,"scale":1},{"node_id":13402403,"draft_id":13402403,"ud_name":"","gen_name":"tabby(3,3,3,3)","notes":"","draft":null,"compressed_draft":null,"draft_visible":true,"loom":null,"loom_settings":{"type":"jacquard","epi":12,"ppi":12,"units":"in","frames":8,"treadles":8},"render_colors":true,"scale":1},{"node_id":63150322,"draft_id":63150322,"ud_name":"","gen_name":"twill(3,3,Z)","notes":"","draft":null,"compressed_draft":null,"draft_visible":true,"loom":null,"loom_settings":{"type":"jacquard","epi":12,"ppi":12,"units":"in","frames":8,"treadles":8},"render_colors":true,"scale":1},{"node_id":64370536,"draft_id":64370536,"ud_name":"","gen_name":"interlacing blend test(tabby(3,3,3,3)+twill(3,3,Z))","notes":"","draft":null,"compressed_draft":null,"draft_visible":true,"loom":null,"loom_settings":{"type":"jacquard","epi":12,"ppi":12,"units":"in","frames":8,"treadles":8},"render_colors":true,"scale":1}],"ops":[{"node_id":30582212,"name":"interlacing_blend","params":[60,50,0,0],"inlets":[0,0]},{"node_id":61924379,"name":"twill","params":[3,3,0,0],"inlets":[]},{"node_id":52502654,"name":"tabby","params":[3,3,3,3],"inlets":[]},{"node_id":20118245,"name":"tabby","params":[3,3,3,3],"inlets":[]},{"node_id":68760579,"name":"twill","params":[3,3,0,0],"inlets":[]},{"node_id":61422204,"name":"interlacing_blend","params":[53,50,0,1],"inlets":[0,0]}],"notes":[],"materials":[{"id":0,"name":"black","stretch":1,"insert":true,"visible":true,"color":"#333333","thickness":100,"diameter":1,"type":0,"notes":"","rgb":{"r":51,"g":51,"b":51}},{"id":1,"name":"white","stretch":1,"insert":true,"visible":true,"color":"#f9f8f3","thickness":100,"diameter":1,"type":0,"notes":"","rgb":{"r":249,"g":248,"b":243}},{"id":2,"name":"red","stretch":1,"insert":true,"visible":true,"color":"#d55e00","thickness":100,"diameter":1,"type":1,"notes":"","rgb":{"r":213,"g":94,"b":0}},{"id":3,"name":"orange","stretch":1,"insert":true,"visible":true,"color":"#e69f00","thickness":100,"diameter":1,"type":1,"notes":"","rgb":{"r":230,"g":159,"b":0}},{"id":4,"name":"yellow","stretch":1,"insert":true,"visible":true,"color":"#f0e442","thickness":100,"diameter":1,"type":1,"notes":"","rgb":{"r":240,"g":228,"b":66}},{"id":5,"name":"green","stretch":1,"insert":true,"visible":true,"color":"#4aff4a","thickness":100,"diameter":1,"type":1,"notes":"","rgb":{"r":74,"g":255,"b":74}},{"id":6,"name":"dark green","stretch":1,"insert":true,"visible":true,"color":"#009e73","thickness":100,"diameter":1,"type":1,"notes":"","rgb":{"r":0,"g":158,"b":115}},{"id":7,"name":"dark blue","stretch":1,"insert":true,"visible":true,"color":"#0072b2","thickness":100,"diameter":1,"type":1,"notes":"","rgb":{"r":0,"g":114,"b":178}},{"id":8,"name":"blue","stretch":1,"insert":true,"visible":true,"color":"#56b4e9","thickness":100,"diameter":1,"type":1,"notes":"","rgb":{"r":86,"g":180,"b":233}},{"id":9,"name":"violet","stretch":1,"insert":true,"visible":true,"color":"#cc79a7","thickness":100,"diameter":1,"type":1,"notes":"","rgb":{"r":204,"g":121,"b":167}},{"id":10,"name":"grey","stretch":1,"insert":true,"visible":true,"color":"#aaaaaa","thickness":100,"diameter":1,"type":1,"notes":"","rgb":{"r":170,"g":170,"b":170}}],"indexed_image_data":[]} \ No newline at end of file diff --git a/projects/docs/docs/reference/operations/cloth/interlacing_blend/interlacing_blend.png b/projects/docs/docs/reference/operations/cloth/interlacing_blend/interlacing_blend.png new file mode 100644 index 000000000..fb9a3709a Binary files /dev/null and b/projects/docs/docs/reference/operations/cloth/interlacing_blend/interlacing_blend.png differ