Or, for packed hexagons:
(() => {
// Packed polygons
// MAIN -----------------------------------------------------------------
const ogJSContext = () => {
// main :: IO ()
const main = () => {
const
radius = 50,
XCenter = 300,
YCenter = 300,
cnv = document.portfolio.canvases[0];
return (
// Middle hexagon,
ogHexagon(
cnv, 0, XCenter, YCenter, radius
),
// list of centers for surrounding hexagons, and
rotatedPolygon(
Math.PI / 2, 6, XCenter, YCenter, radius * Math.sqrt(3)
)
// surrounding hexagons themselves.
.forEach(
tplXY => ogHexagon(
cnv, 0, tplXY[0], tplXY[1], radius
)
),
'Seven packed hexagons created;'
);
};
// ogHexagon :: OGCanvas -> Real -> Real -> Real -> Real -> OGShape
const ogHexagon = (cnv, rotation, cx, cy, radius) =>
Object.assign(cnv.newShape(), {
shapeControlPoints: concatMap(
tpl => replicate(3, new Point(tpl[0], tpl[1])),
rotatedPolygon(rotation, 6, cx, cy, radius)
)
});
// pointFromRadialVector :: Real -> Real -> Real -> Real -> Point
const pointFromRadialVector = (ox, oy, angle, distance) => {
const delta = (f, from) => f(angle) * distance + from;
return Tuple(
delta(Math.cos, ox),
delta(Math.sin, oy)
);
};
// rotatedPolygon :: Real -> Int
// -> Real -> Real -> Real -> (Real, Real)
const rotatedPolygon = (rotation, n, cx, cy, radius) => {
const d = (Math.PI * 2) / n;
return map(
i => pointFromRadialVector(
cx, cy, (d * i) + rotation, radius
),
enumFromToInt(0, n - 1)
);
};
// GENERIC FUNCTIONS ----------------------------------------------
// Tuple (,) :: a -> b -> (a, b)
const Tuple = (a, b) => ({
type: 'Tuple',
'0': a,
'1': b,
length: 2
});
// concat :: [[a]] -> [a]
// concat :: [String] -> String
const concat = xs =>
xs.length > 0 ? (() => {
const unit = typeof xs[0] === 'string' ? '' : [];
return unit.concat.apply(unit, xs);
})() : [];
// enumFromToInt :: Int -> Int -> [Int]
const enumFromToInt = (m, n) =>
n >= m ? Array.from({
length: Math.floor(n - m) + 1
}, (_, i) => m + i) : [];
// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) => xs.map(f);
// concatMap :: (a -> [b]) -> [a] -> [b]
const concatMap = (f, xs) =>
[].concat.apply([], xs.map(f));
// replicate :: Int -> a -> [a]
const replicate = (n, x) =>
Array.from({
length: n
}, () => x);
// showJSON :: a -> String
const showJSON = x => JSON.stringify(x, null, 2);
// MAIN -------------------------------------------
return main();
};
return Application('OmniGraffle')
.evaluateJavascript(
'(' + ogJSContext + ')()'
);
})();