Vera de Pont

Coat

PARAMETRIC COAT

Copy this code and paste it into the “Hyperobjects” website:

 let controlsPadding = 150

model.setSize({width: 2000,height: 2000})
let fillColor = '#c0f3e1';
let outerPathsColor = 'black';
let innerPathsColor = 'rgb(100,200,200)';
let backTranslation = 800;
let connectionOffset = 30;
let connectorsOffset = connectionOffset/2;
let connectorSpacing = 70
let connectorHoleRadius = 5
let connectorPadding = connectionOffset / 2
/**

* generateConnectors function
* * Receives a path and creates a regular pattern of points * evenly spaced based on the global variable connectorSpacing.
* The points will always start and end at the start/end of the path. * When a count is given, the nr of points are not calculated but that is used.
* @param path path along which the points are generated * @return group point group of evenly

*/

function generateConnectors(path, count) {
let length = path.length()
let nrOfPoints = Math.round((length - connectorPadding*2)/connectorSpacing)
if(nrOfPoints < 1) { nrOfPoints = 1 }
if(count !== undefined) {
nrOfPoints = count }
let points = _.range (nrOfPoints+1).map((val) => {
return path.interpolate(val/nrOfPoints * (1 - connectorPadding * 2 / length) + connectorPadding/length)

})
return new Group(points).fill('white').fillOpacity(1).radius(connectorHoleRadius).export(true)
}

/**
* Add two editable points with constraints.
* These two points will be draggable at the top of the model canvas.
* The interpolation control point provides the scalar from 0 to 1 which is from S to L
*/

model.addEditableGeometry(
'interpolation-control-point',
new Group([
{x: model.size.width/2, y: 40,
constraints: {
x: {min: controlsPadding, max: model.size.width - controlsPadding},
y: {min: 40, max: 40}
}

},

])

)

// The spacing control point defines a scalar which does not modify the silhouette.
// Its value is used to add a translation to each of the coat pattern elements
// so that they can be viewed and selected separately.
model.addEditableGeometry(
'spacing-control-point',
new Group([
{x: controlsPadding, y: 120,
constraints: { x: {min: controlsPadding, max: model.size.width - controlsPadding},
y: {min: 120, max: 120} }
},
])
)

// The zero point is the reference point for the layout,
// at the center of the canvas.

let zero = {
x: 1000,
y: 1000
}

// Adding interpolation paths for each of the Coat silhouette points
model.addEditableGeometry(

'collar-front',
new Path([
{x: zero.x , y: zero.y - 531 },
{x: zero.x , y: zero.y - 557 }
])
)

model.addEditableGeometry(
'collar-back',
new Path([
{x: zero.x , y: zero.y - 590 },
{x: zero.x , y: zero.y - 630 }
])
)

model.addEditableGeometry(
'collar-shoulder',
new Path([
{x: zero.x - 111 , y: zero.y - 604 },
{x: zero.x - 129, y: zero.y - 645 }
])
)

model.addEditableGeometry(
'collar-anchor',
new Path([
{x: zero.x - 111 , y: zero.y - 531 },
{x: zero.x - 129, y: zero.y - 557 }
])
)

model.addEditableGeometry(
'collar-back-anchor',
new Path([ {x: zero.x - 80 , y: zero.y - 590 }, {x: zero.x - 98, y: zero.y - 630 } ]))

model.addEditableGeometry(
'shoulder',
new Path([ {x: zero.x - 165 , y: zero.y - 583 }, {x: zero.x - 210, y: zero.y - 614 }
])
)
model.addEditableGeometry(
'sleeve-top',
new Path([

{x: zero.x - 735 , y: zero.y - 347 },

{x: zero.x - 820, y: zero.y - 385 }

])

)

model.addEditableGeometry(

'sleeve-bottom',

new Path([

{x: zero.x - 720 , y: zero.y - 210 },

{x: zero.x - 797, y: zero.y - 198 }

])

)

model.addEditableGeometry(

'sleeve-inner-bottom',

new Path([

{x: zero.x - 377 , y: zero.y - 268 },

{x: zero.x - 430, y: zero.y - 265 }

])

)

model.addEditableGeometry(

'sleeve-inner-side',

new Path([

{x: zero.x - 280 , y: zero.y - 205 },

{x: zero.x - 335, y: zero.y - 180 }

])

)

model.addEditableGeometry(

'sleeve-curve-anchor',

new Path([

{x: zero.x , y: zero.y - 197 },

{x: zero.x - 94, y: zero.y - 252 }

])

)

model.addEditableGeometry(

'sleeve-bottom-curve-anchor',

new Path([

{x: zero.x - 281 , y: zero.y - 269 },

{x: zero.x - 335, y: zero.y - 269 }

])

)

model.addEditableGeometry(

'sleeve-bottom-connect',

new Path([

{x: zero.x - 280 , y: zero.y - 106 },

{x: zero.x - 335, y: zero.y - 100 }

])

)

model.addEditableGeometry(

'bottom',

new Path([

{x: zero.x - 280 , y: zero.y },

{x: zero.x - 335, y: zero.y }

])

)

model.addProcedure(

'components',

(self) => {

let interpolation = self.geometries['interpolation-control-point']

interpolation = (interpolation.points[0].x-controlsPadding) / (model.size.width-controlsPadding*2)

interpolation = _.clamp(interpolation, 0, 1)

let spacing = self.geometries['spacing-control-point']

spacing = (spacing.points[0].x-controlsPadding) / (model.size.width-controlsPadding*2)

spacing = _.clamp(spacing, 0, 1)

// get collar front point

let collarFront = self.geometries['collar-front'].interpolate(interpolation)

let collarBack = self.geometries['collar-back'].interpolate(interpolation)

let collarShoulder = self.geometries['collar-shoulder'].interpolate(interpolation)

let collarBackShoulder = self.geometries['collar-shoulder'].interpolate(interpolation)

let shoulder = self.geometries['shoulder'].interpolate(interpolation)

let sleeveTop = self.geometries['sleeve-top'].interpolate(interpolation)

let sleeveBottom = self.geometries['sleeve-bottom'].interpolate(interpolation)

let sleeveInnerBottom = self.geometries['sleeve-inner-bottom'].interpolate(interpolation)

let sleeveInnerSide = self.geometries['sleeve-inner-side'].interpolate(interpolation)

let sleeveBottomConnect = self.geometries['sleeve-bottom-connect'].interpolate(interpolation)

let bottom = self.geometries['bottom'].interpolate(interpolation)

let collarAnchor = self.geometries['collar-anchor'].interpolate(interpolation)

let collarBackAnchor = self.geometries['collar-back-anchor'].interpolate(interpolation)

let sleeveCurveAnchor = self.geometries['sleeve-curve-anchor'].interpolate(interpolation)

let sleeveBottomCurveAnchor = self.geometries['sleeve-bottom-curve-anchor'].interpolate(interpolation)

collarShoulder.q = collarAnchor

collarBackShoulder.q = collarBackAnchor

sleeveBottomConnect.q = sleeveCurveAnchor

sleeveInnerBottom.q = sleeveBottomCurveAnchor

let controlPoints = new Group([zero,

collarFront,

collarShoulder,

shoulder,

sleeveTop,

sleeveBottom,

sleeveBottomConnect,

sleeveInnerBottom,

sleeveInnerSide,

collarAnchor,

sleeveCurveAnchor,

sleeveBottomCurveAnchor,

bottom]).radius(5).setStrokeWidth(3)

/**

* Create connection lines for connectors

*/

/**

* Inner Sleeve

*/

let innerConnectLine = new Path([

collarShoulder,

shoulder,

sleeveBottomConnect,

bottom

]).fillOpacity(0)

.export(true)

.setStrokeWidth(3)

.stroke(innerPathsColor)

let innerSleeveConnectLine = new Path([

shoulder,

sleeveBottomConnect

])

.fillOpacity(0)

.export(true)

.setStrokeWidth(3)

.stroke(innerPathsColor)

let innerSleeveOverlap = innerSleeveConnectLine.offset(-connectionOffset)

let innerSleeveConnectorsOffset = innerSleeveConnectLine.offset(-connectorsOffset)

let innerArmConnectors = generateConnectors(innerSleeveConnectorsOffset)

let innerArmOffset = innerConnectLine.offset(-connectionOffset)

/**

* Bottom Sleeve

*/

let bottomSleeveConnectLine = new Path([

sleeveBottomConnect,

sleeveInnerSide,

sleeveInnerBottom,

sleeveBottom

]).fillOpacity(0)

.export(true)

.setStrokeWidth(3)

.stroke(innerPathsColor)

let bottomSleeveOffset = bottomSleeveConnectLine.offset(connectionOffset)

let bottomSleeveConnectorsOffset = bottomSleeveConnectLine.offset(connectorsOffset)

let bottomSleeveConnectorsFront = generateConnectors(bottomSleeveConnectorsOffset)

let bottomSleeveConnectorsNegativeOffset = bottomSleeveConnectLine.offset(-connectorsOffset)

let bottomSleeveConnectorsBack = generateConnectors(bottomSleeveConnectorsNegativeOffset, bottomSleeveConnectorsFront.points.length-1)

/**

* Top Sleeve

*/

let topSleeveConnectLine = new Path([

sleeveTop,

shoulder

]).fillOpacity(0)

.export(true)

.setStrokeWidth(3)

.stroke(innerPathsColor)

let topSleeveOffset = topSleeveConnectLine.offset(connectionOffset)

let topSleeveConnectorsOffset = topSleeveConnectLine.offset(connectorsOffset)

let topSleeveConnectorsNegativeOffset = topSleeveConnectLine.offset(-connectorsOffset)

let topSleeveConnectorsFront = generateConnectors(topSleeveConnectorsOffset)

let topSleeveConnectorsBack = generateConnectors(topSleeveConnectorsNegativeOffset)

/**

* Front Zipper

*/

let frontZipperLine = new Path([

collarFront,

zero

]).fillOpacity(0)

.export(true)

.setStrokeWidth(3)

.stroke(innerPathsColor)

let frontZipperOffset = frontZipperLine.copy().offset(connectionOffset/2)

let frontZipperConnectors = generateConnectors(frontZipperLine)

let backZipperLine = new Path([

collarBack,

zero

]).fillOpacity(0)

.export(true)

.setStrokeWidth(3)

.stroke(innerPathsColor)

let backZipperOffset = backZipperLine.offset(connectionOffset/2)

let backZipperConnectors = generateConnectors(backZipperLine)

/**

* Shoulder Connectors

*/

let shoulderLine = new Path([

collarShoulder,

shoulder

])

let shoulderLineConnectorOffset = shoulderLine.offset(-connectorsOffset)

let shoulderLineConnectorNegativeOffset = shoulderLine.offset(connectorsOffset)

let shoulderConnectors = generateConnectors(shoulderLineConnectorOffset)

let shoulderConnectorsBack = generateConnectors(shoulderLineConnectorNegativeOffset)

/**

* Side Connectors

*/

let sideLine = new Path([

sleeveBottomConnect,

bottom

])

let sideConnectors = generateConnectors(sideLine.copy().offset(-connectorsOffset))

let sideConnectorsBack = generateConnectors(sideLine.copy().offset(connectorsOffset))

/**

* Create the pattern elements based on interpolation points

* as well as the offset connection lines.

* get the offset because that is where the fabric should cut

* add the rest of the outline points afterwards

*/

// FRONT

let frontLeftPoints = innerArmOffset.points.slice()

frontLeftPoints.push(bottom)

frontLeftPoints.push(zero)

frontLeftPoints.push(frontZipperOffset.points[1])

frontLeftPoints.push(frontZipperOffset.points[0])

frontLeftPoints.push(collarFront)

frontLeftPoints.push(collarShoulder)

let frontLeft = new Path(frontLeftPoints).setStrokeWidth(2)

.fill(fillColor)

.closed(true)

.export(true)

let frontRightPoints = innerArmOffset.points.slice()

frontRightPoints.push(bottom)

frontRightPoints.push(zero)

frontRightPoints.push(zero)

frontRightPoints.push(collarFront)

frontRightPoints.push(collarShoulder)

let frontRight = new Path(frontRightPoints).setStrokeWidth(2)

.fill(fillColor)

.closed(true)

.export(true)

// BACK

let backLeftPoints = innerSleeveOverlap.points.slice(0, innerSleeveOverlap.points.length - 2)

backLeftPoints.push({x: sleeveBottomConnect.x, y: sleeveBottomConnect.y})

backLeftPoints.push(bottom)

backLeftPoints.push(zero)

backLeftPoints.push(backZipperOffset.points[1])

backLeftPoints.push(backZipperOffset.points[0])

backLeftPoints.push(collarBack)

backLeftPoints.push(collarBackShoulder)

backLeftPoints.push(shoulder)

let backRightPoints = innerSleeveOverlap.points.slice(0, innerSleeveOverlap.points.length - 2)

backRightPoints.push({x: sleeveBottomConnect.x, y: sleeveBottomConnect.y})

backRightPoints.push(bottom)

backRightPoints.push(zero)

backRightPoints.push(collarBack)

backRightPoints.push(collarBackShoulder)

backRightPoints.push(shoulder)

let backLeft = new Path(backLeftPoints).setStrokeWidth(2)

.fill(fillColor)

.closed(true)

.export(true)

let backRight = new Path(backRightPoints).setStrokeWidth(2)

.fill(fillColor)

.closed(true)

.export(true)

let sleevePoints = topSleeveOffset.points.slice()

sleevePoints.push(shoulder)

sleevePoints.push(sleeveBottomConnect)

bottomSleeveOffset.points.slice().forEach((p) => {

sleevePoints.push(p)

})

sleevePoints.push(sleeveBottom)

sleevePoints.push(sleeveTop)

let sleeve = new Path(sleevePoints).setStrokeWidth(2)

.fill(fillColor)

.closed(true)

.export(true)

let sleeveBack = new Path([

shoulder,

sleeveBottomConnect,

sleeveInnerSide,

sleeveInnerBottom,

sleeveBottom,

sleeveTop

])

.setStrokeWidth(2)

.fill(fillColor)

.closed(true)

.export(true)

let full = new Path([

zero,

collarFront,

collarShoulder,

shoulder,

sleeveTop,

sleeveBottom,

sleeveBottomConnect,

bottom,

]).setStrokeWidth(0).fill(fillColor)

let spacing_scalar = 100;

let frontLeftGroup = [

frontLeft.copy(),

innerConnectLine.copy(),

shoulderConnectors.copy(),

innerArmConnectors.copy(),

sideConnectors.copy(),

frontZipperConnectors.copy()

].map((g) => { return g.translate({x: -spacing * spacing_scalar, y: 0})})

let frontRightGroup = [

frontLeft.copy(),

innerConnectLine.copy(),

shoulderConnectors.copy(),

innerArmConnectors.copy(),

sideConnectors.copy(),

frontZipperConnectors.copy()

].map((g) => {

return g.scale({x: -1, y: 1}, zero)

.translate({x: spacing * spacing_scalar, y: 0})

})

let backLeftGroup = [

backLeft.copy(),

innerSleeveConnectLine.copy(),

shoulderConnectorsBack.copy(),

innerArmConnectors.copy(),

sideConnectorsBack.copy(),

backZipperConnectors.copy()

].map((g) => {

return g.translate({x: -spacing * spacing_scalar, y: backTranslation})

})

let backRightGroup = [

backLeft.copy(),

shoulderConnectorsBack.copy(),

innerSleeveConnectLine.copy(),

innerArmConnectors.copy(),

sideConnectorsBack.copy(),

backZipperConnectors.copy()

].map((g) => {

return g.scale({x: -1, y: 1}, zero)

.translate({x: spacing * spacing_scalar, y: backTranslation})

})

let frontLeftSleeveGroup = [

sleeve,

topSleeveConnectLine,

bottomSleeveConnectLine,

innerArmConnectors.copy(),

topSleeveConnectorsFront.copy(),

bottomSleeveConnectorsFront.copy()

].map((g) => {

return g.translate({x: -spacing * spacing_scalar * 2, y: 0})

})

let frontRightSleeveGroup = frontLeftSleeveGroup.map((g) => {

return g.copy().scale({x: -1, y: 1}, zero)

})

let backLeftSleeveGroup = [

sleeveBack,

innerArmConnectors.copy(),

topSleeveConnectorsBack.copy(),

bottomSleeveConnectorsBack.copy()

].map((g) => {

return g.translate({x: -spacing * spacing_scalar * 2, y: backTranslation})

})

let backRightSleeveGroup = backLeftSleeveGroup.map((g) => {

return g.copy().scale({x: -1, y: 1}, zero)

})

return [controlPoints]

.concat(frontLeftGroup)

.concat(frontRightGroup)

.concat(backLeftGroup)

.concat(backRightGroup)

.concat(frontLeftSleeveGroup)

.concat(frontRightSleeveGroup)

.concat(backLeftSleeveGroup)

.concat(backRightSleeveGroup)

}

)