Skip to content

Instantly share code, notes, and snippets.

@icio
Created July 18, 2014 10:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save icio/0c07b374b222760204fd to your computer and use it in GitHub Desktop.
Save icio/0c07b374b222760204fd to your computer and use it in GitHub Desktop.
Fit polygon in box
<!--
https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9
-->
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Polytext</title>
<style type="text/css">
.polytext {
float: left;
height: 300px;
width: 400px;
margin: 20px;
border: 1px solid black;
font-family: Helvetica;
font-size: 10px;
}
</style>
<script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.2/raphael-min.js"></script>
<script type="text/javascript">
/**
* Render a regular polygon with number of sides equal to the number of
* labels. Assumptions
* 1. each label exists on only one line;
* 2. the first point of the polygon is at the top.
*
* @param {Array<String>} labels
* @param {Number} x
* @param {Number} y
* @param {Number} height
* @param {Number} width
* @param {Function} labelSetup
*/
function polytext(paper, labels, x, y, width, height, labelSetup, debug) {
if (debug) paper.rect(x, y, width, height).attr("stroke", "red");
var n = labels.length;
if (n < 3) {
throw "Cannot yet handle simpler than triangles";
}
var cx = x + width / 2, cy = y + height / 2;
// Create and show the labels
// var labels = labels.map(function(label) {
// return paper.text(0, 0, label);
// });
// if (labelSetup) labels.forEach(labelSetup);
var na = 2 * Math.PI / n;
// The tallest polygon which is going to fit into our bbox.
var heightR = (height / 2), topOffset = 0;
if (n & 1) {
var alpha = na * Math.floor(n / 2);
var shortfall = heightR / 2 * (1 + Math.cos(alpha));
heightR += shortfall;
topOffset += shortfall;
console.log(n, Math.cos(alpha), heightR, shortfall, topOffset);
}
// heightROffset = (n & 1) * heightR * (1 - Math.cos(na * Math.floor(n / 2))/2),
// topOffset = -heightROffset / 2;
// heightR += heightROffset;
// The largest polygon which is going to fit into our bbox.
// We have constrained the radius to that imposed by the width of our
// bounding box. The sin calculation is to account for points of our
// polygon which do not touch the right-most point of the bounding
// circle we are calculating the radius of.
var widthR = (width / 2) / Math.sin(na * Math.floor(1 + n / 4));
if (false && widthR < r) {
var r = widthR;
} else {
var r = heightR;
cy += topOffset;
}
if (debug) {
var path = "M " + labels.map(function(l, i) {
return (cx + r * Math.sin(na * i)) + ", " +
(cy + r * -Math.cos(na * i));
}).join(" L ") + " z";
paper.path(path).attr({"stroke": "green", "stroke-width": "2px"});
paper.circle(cx, cy, r).attr("stroke", "green");
}
}
Raphael(function() {
var tests = document.getElementsByClassName("polytext");
for (var i = 0, l = tests.length; i < l; i++) {
var test = tests[i];
var labels = JSON.parse(test.getAttribute("data-labels"));
var paper = Raphael(test, function() {
polytext(
this, labels,
0.1 * this.width, 0.1 * this.height, 0.8 * this.width, 0.8 * this.height,
null, true
);
});
}
});
</script>
</head>
<body>
<div class="polytext" data-labels='["x", "y", "z"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y"]'></div>
<div class="polytext" data-labels='["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]'></div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment