Skip to content

Instantly share code, notes, and snippets.

@HarryStevens
Last active December 20, 2018 17:28
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 HarryStevens/5fe49df19892c04dfb9883c217571409 to your computer and use it in GitHub Desktop.
Save HarryStevens/5fe49df19892c04dfb9883c217571409 to your computer and use it in GitHub Desktop.
Rotate A Point About An Origin
license: gpl-3.0

Rotate a point about an origin by a specified angle. Read more on Wikipedia and StackExchange.

The red point represents the rotation of the blue point around the black point by 45 degrees. By dragging, you can adjust the position of the blue point and the black point, and the angle of rotation of the red point.

This block uses Geometric.js for all geometric functions, specifically lineAngle, lineLength, lineMidpoint, pointRotate and pointTranslate.

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
body {
margin: 0;
}
circle {
cursor: move;
}
.point {
fill: steelblue;
}
.point-line {
stroke: steelblue;
}
.rotated-point {
fill: tomato;
}
.rotated-point-line {
stroke: tomato;
}
text {
fill: #fff;
font-family: "Helvetica Neue", sans-serif;
pointer-events: none;
text-anchor: middle;
text-shadow: -3px -3px 1px rgba(195,136,192, 0.4), -3px -2px 1px rgba(195,136,192, 0.4), -3px -1px 1px rgba(195,136,192, 0.4), -3px 0px 1px rgba(195,136,192, 0.4), -3px 1px 1px rgba(195,136,192, 0.4), -3px 2px 1px rgba(195,136,192, 0.4), -3px 3px 1px rgba(195,136,192, 0.4), -2px -3px 1px rgba(195,136,192, 0.4), -2px -2px 1px rgba(195,136,192, 0.4), -2px -1px 1px rgba(195,136,192, 0.4), -2px 0px 1px rgba(195,136,192, 0.4), -2px 1px 1px rgba(195,136,192, 0.4), -2px 2px 1px rgba(195,136,192, 0.4), -2px 3px 1px rgba(195,136,192, 0.4), -1px -3px 1px rgba(195,136,192, 0.4), -1px -2px 1px rgba(195,136,192, 0.4), -1px -1px 1px rgba(195,136,192, 0.4), -1px 0px 1px rgba(195,136,192, 0.4), -1px 1px 1px rgba(195,136,192, 0.4), -1px 2px 1px rgba(195,136,192, 0.4), -1px 3px 1px rgba(195,136,192, 0.4), 0px -3px 1px rgba(195,136,192, 0.4), 0px -2px 1px rgba(195,136,192, 0.4), 0px -1px 1px rgba(195,136,192, 0.4), 0px 1px 1px rgba(195,136,192, 0.4), 0px 2px 1px rgba(195,136,192, 0.4), 0px 3px 1px rgba(195,136,192, 0.4), 1px -3px 1px rgba(195,136,192, 0.4), 1px -2px 1px rgba(195,136,192, 0.4), 1px -1px 1px rgba(195,136,192, 0.4), 1px 0px 1px rgba(195,136,192, 0.4), 1px 1px 1px rgba(195,136,192, 0.4), 1px 2px 1px rgba(195,136,192, 0.4), 1px 3px 1px rgba(195,136,192, 0.4), 2px -3px 1px rgba(195,136,192, 0.4), 2px -2px 1px rgba(195,136,192, 0.4), 2px -1px 1px rgba(195,136,192, 0.4), 2px 0px 1px rgba(195,136,192, 0.4), 2px 1px 1px rgba(195,136,192, 0.4), 2px 2px 1px rgba(195,136,192, 0.4), 2px 3px 1px rgba(195,136,192, 0.4), 3px -3px 1px rgba(195,136,192, 0.4), 3px -2px 1px rgba(195,136,192, 0.4), 3px -1px 1px rgba(195,136,192, 0.4), 3px 0px 1px rgba(195,136,192, 0.4), 3px 1px 1px rgba(195,136,192, 0.4), 3px 2px 1px rgba(195,136,192, 0.4), 3px 3px 1px rgba(195,136,192, 0.4);
}
path {
fill: purple;
fill-opacity: .5;
stroke: purple;
stroke-dasharray: 5, 5;
pointer-events: none;
}
</style>
</head>
<body>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://unpkg.com/geometric@1.0.0/build/geometric.js"></script>
<script>
var width = window.innerWidth, height = window.innerHeight;
var svg = d3.select("body").append("svg").attr("width", width).attr("height", height);
var anglePath = svg.append("path");
var origin_position = [width / 2, height / 2];
var point_position = origin_position.map((d, i) => d -= (i === 0 ? 45 : 100));
var rotation = 45;
var rotated_point_position = geometric.pointRotate(point_position, rotation, origin_position);
var point_line = svg.append("line").attr("class", "point-line");
var point = svg.append("circle")
.attr("r", 5)
.attr("class", "point")
.call(d3.drag().on("drag", _ => {
point_position[0] = event.pageX;
point_position[1] = event.pageY;
rotated_point_position = geometric.pointRotate(point_position, rotation, origin_position);
drawAngle();
drawPoint();
drawPointLine();
drawRotatedPoint();
drawRotatedPointLine();
}));
var rotated_point_line = svg.append("line").attr("class", "rotated-point-line");
var rotated_point = svg.append("circle")
.attr("r", 5)
.attr("class", "rotated-point")
.call(d3.drag().on("drag", _ => {
rotation = geometric.lineAngle([origin_position, [event.pageX, event.pageY]]) - geometric.lineAngle([origin_position, point_position]);
rotated_point_position = geometric.pointRotate(point_position, rotation, origin_position);
drawAngle();
drawRotatedPoint();
drawRotatedPointLine();
}));
var origin = svg.append("circle")
.attr("r", 5)
.attr("class", "origin")
.call(d3.drag().on("drag", _ => {
var point_distance = geometric.lineLength([origin_position, point_position]);
var point_angle = geometric.lineAngle([origin_position, point_position]);
origin_position[0] = event.pageX;
origin_position[1] = event.pageY;
point_position = geometric.pointTranslate(origin_position, point_angle, point_distance);
rotated_point_position = geometric.pointRotate(point_position, rotation, origin_position);
drawAngle();
drawOrigin();
drawPoint();
drawPointLine();
drawRotatedPoint();
drawRotatedPointLine();
}));
var angleText = svg.append("text").attr("dx", 3.5);
drawOrigin();
drawPointLine();
drawPoint();
drawRotatedPoint();
drawRotatedPointLine();
drawAngle();
function drawAngle(){
angleText
.attr("transform", "translate(" + geometric.lineMidpoint([point_position, rotated_point_position]) + ")")
.text(Math.round(rotation > 180 ? 360 - rotation : rotation < -180 ? 360 + rotation : Math.abs(rotation)) + "°");
var d = geometric.lineLength([point_position, rotated_point_position]);
anglePath
.attr("d", "M" + ((rotation < 0 && rotation > -180) || rotation > 180 ? rotated_point_position : point_position) + "A" + d + "," + d + " 0 0,1 " + ((rotation < 0 && rotation > -180) || rotation > 180 ? point_position : rotated_point_position) + " L" + origin_position + " Z")
}
function drawOrigin(){
origin.attr("transform", "translate(" + origin_position + ")");
}
function drawPoint(){
point.attr("transform", "translate(" + point_position + ")");
}
function drawPointLine(){
point_line
.attr("x1", point_position[0])
.attr("y1", point_position[1])
.attr("x2", origin_position[0])
.attr("y2", origin_position[1]);
}
function drawRotatedPoint(){
rotated_point.attr("transform", "translate(" + rotated_point_position + ")");
}
function drawRotatedPointLine(){
rotated_point_line
.attr("x1", rotated_point_position[0])
.attr("y1", rotated_point_position[1])
.attr("x2", origin_position[0])
.attr("y2", origin_position[1]);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment