Skip to main content

Create Patterns

These are the custom patterns that you can implement in your applications:


Rectangular

There are many ways to define a rectangular pattern, the following are some examples based on the number of copies or the size-dependent variables. In both cases the pattern is separated into two functions: one for the positions and the other for the pattern sketch.

By Number Of Copies

function getPatternPositions(nrCopiesVector: SKYMATH.Vector2D, distanceVector: SKYMATH.Vector2D) {
const positions = []

for (let i = 0; i < nrCopiesVector.x; i++) {
for (let j = 0; j < nrCopiesVector.y; j++) {
const position = new SKYMATH.Vector2D(i * distanceVector.x, j * distanceVector.y)
positions.push(position)
}
}

return positions
}

export function generateRectangularPatternSketch(
sketchToUseInPattern: SKYCAD.Sketch,
nrCopiesVector: SKYMATH.Vector2D,
distanceVector: SKYMATH.Vector2D,
) {
const patternSketch = new SKYCAD.Sketch()
const patternPositions = getPatternPositions(nrCopiesVector, distanceVector)

patternPositions.forEach((position) => {
const clonedSketch = sketchToUseInPattern.clone()
clonedSketch.translate(position.x, position.y)
patternSketch.mergeSketch(clonedSketch)
})

return patternSketch
}

By Size

export function getPatternPositions(
lengthVector: SKYMATH.Vector2D,
distanceBetweenVector: SKYMATH.Vector2D,
holeSize: number,
autocentered: boolean,
) {
const nrCopiesX = Math.floor(lengthVector.x / (holeSize + distanceBetweenVector.x))
const nrCopiesY = Math.floor(lengthVector.y / (holeSize + distanceBetweenVector.y))
const nrCopiesVector = new SKYMATH.Vector2D(nrCopiesX, nrCopiesY)

const startOffset = autocentered
? new SKYMATH.Vector2D(
(lengthVector.x - nrCopiesX * holeSize - (nrCopiesX - 1) * distanceBetweenVector.x) / 2,
(lengthVector.y - nrCopiesY * holeSize - (nrCopiesY - 1) * distanceBetweenVector.y) / 2,
)
: new SKYMATH.Vector2D(0, 0)

const positions = []
for (let i = 0; i < nrCopiesVector.x; i++) {
for (let j = 0; j < nrCopiesVector.y; j++) {
const position = new SKYMATH.Vector2D(
startOffset.x + i * (holeSize + distanceBetweenVector.x),
startOffset.y + j * (holeSize + distanceBetweenVector.y),
)
positions.push(position)
}
}

return positions
}

export function generateRectangularPatternSketch(
sketchToUseInPattern: SKYCAD.Sketch,
lengthVector: SKYMATH.Vector2D,
distanceBetweenVector: SKYMATH.Vector2D,
holeSize: number,
autocentered: boolean,
) {
const patternSketch = new SKYCAD.Sketch()
const patternPositions = getPatternPositions(lengthVector, distanceBetweenVector, holeSize, autocentered)

patternPositions.forEach((position) => {
const clonedSketch = sketchToUseInPattern.clone()
clonedSketch.translate(position.x, position.y)
patternSketch.mergeSketch(clonedSketch)
})

return patternSketch
}


Circular

Here is an example of a circular pattern, separated into two functions: one for the positions and the other for the pattern sketch.

export function generateCircularPatternPositionStructs(
radius: number,
nrCopies: number,
{ startAngle = 0, endAngle = 2 * Math.PI, referenceAngle = 0, addLast = false } = {},
) {
const positionStructs: { position: SKYMATH.Vector2D; angle: number }[] = []
const NC = addLast ? nrCopies + 1 : nrCopies
const angleRange = endAngle - startAngle

for (let i = 0; i < NC; i++) {
const angle = (angleRange * i) / nrCopies + startAngle + referenceAngle
const position = new SKYMATH.Vector2D(radius * Math.cos(angle), radius * Math.sin(angle))
positionStructs.push({ position, angle }) // the angle is pushed here so the sketch can be rotated accordingly later
}

return positionStructs
}

export function generateCircularPatternSketch(
sketchToUseInPattern: SKYCAD.Sketch,
radius: number,
nrCopies: number,
{ startAngle = 0, endAngle = 2 * Math.PI, referenceAngle = 0, addLast = false } = {},
) {
const positionStructs = generateCircularPatternPositionStructs(radius, nrCopies, {
startAngle,
endAngle,
referenceAngle,
addLast,
})
const circularPatternSketch = new SKYCAD.Sketch()

positionStructs.forEach((struct) => {
const { position, angle } = struct
const patternSketch = sketchToUseInPattern.clone()
patternSketch.scale(radius / 30) // scale sketch according to radius
patternSketch.rotate(angle) // point inwards
patternSketch.translate(position.x, position.y)
circularPatternSketch.mergeSketch(patternSketch)
})

return circularPatternSketch
}