Rotate rectangle with 4 points using Angular

486 Views Asked by At

I have a rectangle that drawn with 4 points. I need to rotate all points an arbitrary degree and find the new x,y of the points.I try to rotate these but the problem is when I'll increase the degree, rectangle Becomes smaller and when I'll decrease the degree, the first rectangle not drawn again. How can I do this by using Angular.

<div ng-app="myApp">
    <div  ng-app="myApp" ng-controller="rectController">
         <input type="number" ng-model="Rotation" min="-360" max="360" value="0"/>
         <rect-rotate/>
    </div>
 </div>

Here is the JavaScript code:

var App = angular.module('myApp', []);
var Ctrl = App.controller('rectController', function($scope) { });

Ctrl.directive('rectRotate', function() {

        function link(scope, el, attr) {
            var w = 1200, h = 780;
            var width = 300, height = 200;
            var point1=[300,200],point2=[600,200],point3=[600,400],point4=[300,400];

            var svg = d3.select(el[0]).append("svg")
                .attr("width", w)
                .attr("height", h);
            var newg = svg.append("g").data([{ x: width, y: height }]);

             var rect = newg.append("path")
                .attr("x", function(d) {
                    return d.x;
                })
                .attr("y", function(d) {
                    return d.y;
                })
                .attr("fill-opacity", .5)
                .attr("d", function(d) {

        var dCommand
                    = "M" + point1[0] + "," + point1[1] + "L" + point2[0] 
                    + "," + point2[1] + "L " + point3[0] + "," + point3[1] 
                    + "L " + point4[0] + "," + point4[1] + "Z";
                    return dCommand;
                });
         scope.$watch('Rotation', function (newValues) {
            var rotateAngle = newValues;
            rotateAngle = rotateAngle * Math.PI / 180.0;
            var centerX = (point1[0]+point3[0]) / 2;
            var centerY = (point1[1]+point3[1]) / 2;

 //1
 point1[0] = (Math.cos(rotateAngle) * (point1[0] - centerX)
          -(Math.sin(rotateAngle) * (point1[1] - centerY)) + centerX;
 point1[1] = (Math.sin(rotateAngle) * (point1[0] - centerX)) 
          +(Math.cos(rotateAngle) * (point1[1] - centerY)) + centerY;

//2
point2[0] = (Math.cos(rotateAngle) * (point2[0] - centerX)
          -(Math.sin(rotateAngle) * (point2[1] - centerY)) + centerX;
point2[1] = (Math.sin(rotateAngle) * (point2[0] - centerX)) 
          +(Math.cos(rotateAngle) * (point2[1] - centerY)) + centerY;

//3
point3[0] = (Math.cos(rotateAngle) * (point3[0] - centerX)
          -(Math.sin(rotateAngle) * (point3[1] - centerY)) + centerX;
point3[1] = (Math.sin(rotateAngle) * (point3[0] - centerX)) 
          +(Math.cos(rotateAngle) * (point3[1] - centerY)) + centerY;

//4
point4[0] = (Math.cos(rotateAngle) * (point4[0] - centerX)
          -(Math.sin(rotateAngle) * (point4[1] - centerY)) + centerX;
point2[1] = (Math.sin(rotateAngle) * (point4[0] - centerX)) 
          +(Math.cos(rotateAngle) * (point4[1] - centerY)) + centerY;

 rect.attr("d", function (d) {

        var dCommand
                    = "M" + point1[0] + "," + point1[1] + "L" + point2[0] 
                    + "," + point2[1] + "L " + point3[0] + "," + point3[1] 
                    + "L " + point4[0] + "," + point4[1] + "Z";
                    return dCommand;
                    });
        }return {
            link: link
        };

    });
2

There are 2 best solutions below

3
On BEST ANSWER

You should use the rotate attribute as Lars Kotthoff already mentioned.

As you're basically creating a rect I replaced your path with a svg:rect for convenience. The following code does the rotation by rotating the g element. This way you can crate any number of shapes inside and they will rotate properly.

For rotating the g element around the center I calculated the center by adding half of the width and height of the element to its x and y position.

var App = angular.module('myApp', []);
var Ctrl = App.controller('rectController', function($scope) { });

Ctrl.directive('rectRotate', function() {
  function link(scope, el, attr) {
    var w = 1200, h = 780;
    var width = 300, height = 200, positionX = 300, positionY = 200;

    var svg = d3.select(el[0]).append("svg")
        .attr("width", w)
        .attr("height", h);

    var newg = svg.append("g");

    var rect = newg.append("rect")
        .attr("x", positionX)
        .attr("y", positionY)
        .attr("fill-opacity", .5)
        .attr("width", width)
        .attr("height", height);

    scope.$watch('Rotation', function (newValues) {

      var rotateAngle = newValues || 0;
      newg.attr("transform","rotate(" + rotateAngle + " "+ (positionX + width / 2) +" "+ (positionY + height / 2) +")");
    });
  }
  return {link: link};
});
1
On

There is many way to rotate points. You can use matrix to rotate points. Your points coordinates multiple the matrix. Here is links, which may help you.

http://www.euclideanspace.com/maths/geometry/affine/aroundPoint/

Rotate point in rectangle