5

I have code like this:

$(function() {
  var $selection = $('.selection');
  $('li').filter(function() {
    var self = $(this);
    return /* ????? */;
  }).addClass('selected');
});
.widget {
  width: 320px;
  height: 200px;
  border: 1px solid gray;
  position: absolute;
  overflow: scroll;
}
.selection {
  position: absolute;
  top: 90px;
  left: 90px;
  border: 1px dotted black;
  height: 120px;
  width: 120px;
}
ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
li {
  float: left;
  background: blue;
  width: 40px;
  height: 40px;
  margin: 10px;
}
li.selected {
  background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="widget">
  <div class="selection"></div>
  <ul>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</div>

How can I select only those li elements that are intersecting with .selection rectangle?

Greg
  • 21,235
  • 17
  • 84
  • 107
jcubic
  • 61,973
  • 54
  • 229
  • 402
  • https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection – Rayon Dec 17 '16 at 17:27
  • I'm voting to reopen this question as I believe it is different enough to the question marked as the dupe. – Greg Dec 17 '16 at 17:47

2 Answers2

11

Using standard DOM techniques, you can iterate over each LI element and obtain a bounding rectangle, which gives the coordinates of the LI's rectangle.

Do this for the selection rectangle too and then you can simply check whether the coordinates are within the range of the selection's.

Element.getBoundingClientRect()

The Element.getBoundingClientRect() method returns the size of an element and its position relative to the viewport.

The returned value is a DOMRect object which is the union of the rectangles returned by getClientRects() for the element, i.e., the CSS border-boxes associated with the element.

The returned value is a DOMRect object, which contains read-only left, top, right, bottom, x, y, width, height properties describing the border-box in pixels. Properties other than width and height are relative to the top-left of the viewport.

Please see below, the edited code which selects the LI elements that are fully contained or partially intersecting the selection.

var selection = document.querySelector(".selection");
var rectSelection = selection.getBoundingClientRect();

// Iterate over all LI elements.
[].forEach.call(document.querySelectorAll("li"), function(li) {
    var rect = li.getBoundingClientRect();

    if(rect.bottom > rectSelection.top 
    && rect.right > rectSelection.left 
    && rect.top < rectSelection.bottom 
    && rect.left < rectSelection.right) {
        li.classList.add("selected");
    }
});
.widget {
  width: 320px;
  height: 200px;
  border: 1px solid gray;
  position: absolute;
  overflow: scroll;
}
.selection {
  position: absolute;
  top: 90px;
  left: 90px;
  border: 1px dotted black;
  height: 120px;
  width: 120px;
}
ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
li {
  float: left;
  background: blue;
  width: 40px;
  height: 40px;
  margin: 10px;
}
li.selected {
  background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="widget">
  <div class="selection"></div>
  <ul>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</div>
Greg
  • 21,235
  • 17
  • 84
  • 107
  • Work better with the update ;) – Arthur Dec 17 '16 at 17:42
  • @Arthur yeah I noticed that I wasn't selecting the intersecting squares first, only the one fully contained. I hope this is what you were looking for. – Greg Dec 17 '16 at 17:43
  • It can be a option on your function... could be interesting. `red` are on the big square, and green just collide – Arthur Dec 17 '16 at 17:44
  • Wouldn't it be the same result if instead of adding/subtrackting the width/height just use the opposite side like so: `rect.bottom > rectSelection.top && rect.right > rectSelection.left && rect.top < rectSelection.bottom && rect.left < rectSelection.right`? Its much easier to read like this. – H K Jun 16 '22 at 13:44
  • @HK that's a lovely simple solution - I'll update the answer :) – Greg Jun 17 '22 at 15:48
4

The concept to understand box collision Origin answer

If You have to check the 2 rects with rotation you have to make projection of rect corner on the axes of the other rect. If all projections of rect1 hit the rect2, and rect2 projections hit rect1 so the two rect collide.

Some projection don't collide here, the 2 rects are not collide. enter image description here

The 4 projections hit the other rect, the 2 rects are collide. enter image description here

I have made a presentation on this CodePen for more comprehension.

Clone of the code here (it's old and durty, don't be rude it's just to display.. don't look the code to much :p)

function merge_object(obj1, obj2){
    var obj3 = {};
    for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
    for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
    return obj3;
};
/** 
 * Transforme degrees to radians
 */
Math.radians = function(degrees) {
    return degrees * Math.PI / 180;
};
Math.degrees = function(radians) {
  return radians * 180 / Math.PI;
};

/**
 * Square Javascript File
 *
 * -- Changelog
 * Version 1.0.0 (11/05/2013) AGE
 * - Début du versionnement
 *
 * @package js
 * @author AGE
 * @version 1.0.0
 */

// App Object
var collide = {
    
    // Define
    PROJECT_ID : 'collide',
    PROJECT_SPEED : 50, // FPS : 1000/PROJECT_SPEED
    
    FIXED_SQUARE_SIZE : 100,
    FIXED_SQUARE_X : 250,
    FIXED_SQUARE_Y : 250,
    
    CURSOR_SQUARE_SIZE : 50,
        
    // Attribute
    $el : null,
    $ctx : null,
    project_pos_top : null,
    project_pos_left : null,
    width : null,
    height : null,
    
    cursor_x : 0,
    cursor_y : 0,
    
    fixed_angle : 0,
    fixed_rotaton_speed : null,
    cursor_angle : 0,
    cursor_rotaton_speed : null,
     
    draw_approx : true, 
    fixed_projections : {},
    cursor_projections : {},
        
    /**
     * Init Square Game
     */
    __init : function( options ){
        
        // Get element and informations
        collide.$el = $('#' + collide.PROJECT_ID);
        collide.$ctx = collide.$el[0].getContext('2d');
        
        var offset = collide.$el.offset();
        collide.project_pos_top = offset.top;
        collide.project_pos_left = offset.left;
        collide.width = collide.$el.width();
        collide.height = collide.$el.height();
        
        // Events on Move
        collide.$el.mousemove(function(e){
            // Calculate new position
            collide.cursor_x = e.pageX - collide.project_pos_left;           
            collide.cursor_y = e.pageY - collide.project_pos_top;           
        });
        
        $('#cursor_set_angle').change(function(){
            collide.cursor_angle = parseInt($(this).val());
        });
        $('#fixed_set_angle').change(function(){
            collide.fixed_angle = parseInt($(this).val());
        });
        
        // Run the project
        collide.run();
    },
    
    /**
     * Run the project
     */
    run : function(){
                
        // Reset HTML
        $('.corners, .functions, .projections').remove();
        
        // Get 2 angles rotation speed
        collide.fixed_rotaton_speed = parseInt($('#fixed_rotation_speed').val());
        collide.cursor_rotaton_speed = parseInt($('#cursor_rotation_speed').val());
                                
        // Upadte rotation
        collide.fixed_angle = collide.fixed_angle+collide.fixed_rotaton_speed;  
        if(collide.fixed_angle > 360) {collide.fixed_angle -= 360}; 
        if(collide.fixed_angle < 0) {collide.fixed_angle += 360};             
        $('#fixed_angle').val(collide.fixed_angle);

        collide.cursor_angle = collide.cursor_angle+collide.cursor_rotaton_speed;  
        if(collide.cursor_angle > 360) {collide.cursor_angle -= 360}; 
        if(collide.cursor_angle < 0) {collide.cursor_angle += 360}; 
        $('#cursor_angle').val(collide.cursor_angle);

        // Approx Collide
        if(collide.is_approx_collide()){
            
            collide.draw_approx = false;
            
            // Get corners
            var fixer_corner = collide.get_corners(
                collide.FIXED_SQUARE_X,  collide.FIXED_SQUARE_Y, 
                collide.FIXED_SQUARE_SIZE, collide.fixed_angle);
            var cursor_corner = collide.get_corners(
                collide.cursor_x, collide.cursor_y, 
                collide.CURSOR_SQUARE_SIZE, collide.cursor_angle);
                
                
            // Get projections
                // CURSOR on FIXED.X && FIXED.Y
            collide.cursor_projections = collide.get_projections(
                collide.FIXED_SQUARE_X,  collide.FIXED_SQUARE_Y,
                collide.fixed_angle,cursor_corner);  
                // FIXED on CURSOR.X && CURSOR.Y
            collide.fixed_projections = collide.get_projections(
                collide.cursor_x,  collide.cursor_y,
                collide.cursor_angle, fixer_corner);  
                      
        }else{
            collide.draw_approx = true;
        }
        
        collide.draw();
        
        // Re-lauch Run
        setTimeout(function(){
            collide.run();
        }, collide.PROJECT_SPEED);
    },
    
    
    draw : function(){
        // Clear
        collide.$ctx.clearRect(0, 0, collide.width, collide.height);
        collide.$ctx.setTransform(1, 0, 0, 1, 0, 0);
        collide.$ctx.save();
        
        // Draw squares
        collide.draw_square(collide.FIXED_SQUARE_X, collide.FIXED_SQUARE_Y,
            collide.FIXED_SQUARE_SIZE, collide.fixed_angle, '0,0,255');
        
        collide.draw_square(collide.cursor_x, collide.cursor_y,
            collide.CURSOR_SQUARE_SIZE, collide.cursor_angle, '255,128,0');
            
        if(collide.draw_approx){
            
            // Approx 
            collide.draw_approx_square(collide.FIXED_SQUARE_X, collide.FIXED_SQUARE_Y,
                collide.FIXED_SQUARE_SIZE, '0,0,255');

            collide.draw_approx_square(collide.cursor_x, collide.cursor_y,
                collide.CURSOR_SQUARE_SIZE, '255,128,0');
        }   
        else{
            
            // Axes
            collide.draw_axe(collide.FIXED_SQUARE_X, collide.FIXED_SQUARE_Y,
                collide.fixed_angle, '0,0,255');

            collide.draw_axe(collide.cursor_x, collide.cursor_y,
                collide.cursor_angle, '255,128,0');
                
            // Projections
            collide.draw_projections( collide.fixed_projections, '0,0,255');
            collide.draw_projections( collide.cursor_projections, '255,128,0');
            
        }
    },
    draw_square : function(center_x, center_y, size, angle, rgb){
        
        // Is collide ? 
        if(collide.is_approx_collide() && collide.is_collide()){ rgb = "255,0,0"; } 
        
        collide.$ctx.save();
        
        // Draw Fixed square
        collide.$ctx.translate(center_x, center_y);
        collide.$ctx.rotate( Math.radians( angle ) );
        collide.$ctx.fillStyle = 'rgba('+rgb+',.2)';
        collide.$ctx.fillRect(size / -2, size / -2, size, size);
        
        // Draw Corner
        collide.$ctx.translate(size/2, size/2);
        collide.$ctx.beginPath();
        collide.$ctx.fillStyle = 'rgba('+rgb+',1)';
        collide.$ctx.arc(0, 0, 2, 0, Math.PI*2, true); 
        collide.$ctx.closePath();
        collide.$ctx.fill();
        collide.$ctx.translate(-size, 0);
        collide.$ctx.beginPath();
        collide.$ctx.fillStyle = 'rgba('+rgb+',1)';
        collide.$ctx.arc(0, 0, 2, 0, Math.PI*2, true); 
        collide.$ctx.closePath();
        collide.$ctx.fill();
        collide.$ctx.translate(0, -size);
        collide.$ctx.beginPath();
        collide.$ctx.fillStyle = 'rgba('+rgb+',1)';
        collide.$ctx.arc(0, 0, 2, 0, Math.PI*2, true); 
        collide.$ctx.closePath();
        collide.$ctx.fill();
        collide.$ctx.translate(size,0);
        collide.$ctx.beginPath();
        collide.$ctx.fillStyle = 'rgba('+rgb+',1)';
        collide.$ctx.arc(0, 0, 2, 0, Math.PI*2, true); 
        collide.$ctx.closePath();
        collide.$ctx.fill();
        
        collide.$ctx.restore();
    },
    draw_approx_square : function(center_x, center_y, size, rgb){
        
        collide.$ctx.save();
        
        // Draw Fixed square
        collide.$ctx.translate(center_x, center_y);
        collide.$ctx.strokeStyle = 'rgba('+rgb+',1)';
        collide.$ctx.lineWidth = 1;
        collide.$ctx.strokeRect(-size, -size, 2*size, 2*size);
        
        collide.$ctx.restore();        
    },
    draw_axe : function (center_x, center_y, angle, rgb){
        collide.$ctx.save();
        
        collide.$ctx.translate(center_x, center_y);
        collide.$ctx.rotate( Math.radians( angle ) );
        
        collide.$ctx.beginPath();
        collide.$ctx.strokeStyle = 'rgba('+rgb+',1)';
        collide.$ctx.moveTo(-500, 0);
        collide.$ctx.lineTo(500,0);
        collide.$ctx.stroke();
        
        collide.$ctx.restore();
        collide.$ctx.save();
        
        collide.$ctx.translate(center_x, center_y);
        collide.$ctx.rotate( Math.radians( angle+90 ) );
        
        collide.$ctx.beginPath();
        collide.$ctx.strokeStyle = 'rgba('+rgb+',1)';
        collide.$ctx.moveTo(-500,0);
        collide.$ctx.lineTo(500,0);
        collide.$ctx.stroke();
        
        collide.$ctx.restore();  
    },
    draw_projections : function(projections, rgb){
        for(axe in projections){
            for(key in ['min', 'max']){                
                var projection = projections[axe][key==0?"min":"max"];

                collide.$ctx.save();

                collide.$ctx.translate(projection.x, projection.y);
                collide.$ctx.beginPath();
                collide.$ctx.fillStyle = 'rgba('+rgb+',1)';
                collide.$ctx.arc(0, 0, 2, 0, Math.PI*2, true); 
                collide.$ctx.closePath();
                collide.$ctx.fill();  
                
                collide.$ctx.beginPath();
                collide.$ctx.strokeStyle = 'rgba('+rgb+',.2)';
                collide.$ctx.moveTo(00,0);
                collide.$ctx.lineTo(projection.corner.x - projection.x, 
                                    projection.corner.y - projection.y);
                collide.$ctx.stroke();
                collide.$ctx.restore();  
            }
            
            
            collide.$ctx.save();
            
            collide.$ctx.beginPath();
            collide.$ctx.strokeStyle = (projections[axe].is_collide)? 'rgba(255,0,0,1)' : 'rgba('+rgb+',1)'; 
            collide.$ctx.lineWidth = 2;
            collide.$ctx.moveTo(projections[axe].min.x, projections[axe].min.y);
            collide.$ctx.lineTo(projections[axe].max.x,projections[axe].max.y);
            collide.$ctx.stroke();
            
            collide.$ctx.restore(); 
                
            
        }
    },
    
    /**
     * Calculate corners position and draw it
     */    
    get_corners : function(x, y, size, angle){
        var corners = [];
        var radius = parseInt(Math.sqrt(2*size*size)/2);
        
        for(var i_angle=0; i_angle<=270; i_angle+=90){
            var corner = {
                x : parseInt(x + radius * Math.cos(Math.radians(angle + 45 + i_angle) )),
                y : parseInt(y + radius * Math.sin(Math.radians(angle + 45 + i_angle) ))
            };
            corners.push(corner);
        }
        return corners;
    },
    
    /**
     * Calculate square functions and draw it
     */    
    get_functions : function(x, y, size, angle){
        var functions = {
            x : Math.tan(Math.radians( - angle%90)),
            y : Math.tan(Math.radians(90 - angle%90))
        };
        return functions;
    },
    
    get_projections : function(center_x, center_y,angle, corners){
        
        // Genere start Min-Max projection on center of Square
        var projections = {
            "x": {
                'min' : null,
                'max' : null,
                'distance' : null
            },
            "y": {
                'min' : null,
                'max' : null,
                'distance' : null
            }
        };
        
        for(i in corners){
            var corner = corners[i];
            var projection_x = {}, projection_y = {};
            
            /**
             * Global calcul for projection X and Y
             */ 
            
            // Angle 0:horizontale (center > left) 90:verticatale (center > top)
            var angle90 = -(angle%90);
            
            //Distance :
            var distance_corner_center = Math.floor(Math.sqrt((center_x-corner.x)*(center_x-corner.x) + (center_y-corner.y)*(center_y-corner.y)));
            
            // Angle between segment [center-corner] and real axe X (not square axe), must be negative (radius are negative clockwise) 
            var angle_with_axeX = -Math.floor(Math.degrees(Math.atan((corner.y-center_y) / (corner.x-center_x))));  // Tan(alpha) = opposé (ecart sur Y) / adjacent (ecart sur X)
            // If angle is ]0;90[, he is on the 2em et 4th quart of rotation
            if(angle_with_axeX > 0) {angle_with_axeX -= 180;}
            // If corner as upper (so with less pixel on y) thant center, he is on 3th or 4th quart of rotation
            if(corner.y < center_y || (corner.y == center_y && corner.x < center_x) ){angle_with_axeX -= 180;}

            // Calculate difference between 2 angles to know the angle between [center-corner] and Square axe X
            var delta_angle = angle_with_axeX - angle90;
            // If angle is on ]-180;-360], corner are upper than Square axe X, so set a positive angle on [0;180] 
            if(delta_angle < -180){delta_angle += 360;}
            
            /**
             * Projection on X
             */
            
            // Calculate distance between center and projection on axe X
            var distance_center_projection_x = Math.floor(distance_corner_center * Math.cos(Math.radians( delta_angle )));
            
            // Create projection
            projection_x.x = Math.floor(center_x + distance_center_projection_x * Math.cos(Math.radians( -angle90 ))); 
            projection_x.y =  Math.floor(center_y + distance_center_projection_x * Math.sin(Math.radians( -angle90 ))); 
            
            // If is the min ?   
            if(projections.x.min == null
                || distance_center_projection_x < projections.x.min.distance){
            
                projections.x.min = projection_x;
                projections.x.min.distance = distance_center_projection_x;
                projections.x.min.corner = corner;
            }
            // Is the max ?
            if(projections.x.max == null
                || distance_center_projection_x > projections.x.max.distance){
            
                projections.x.max = projection_x;
                projections.x.max.distance = distance_center_projection_x;
                projections.x.max.corner = corner;
            }
            
            /**
             * Projection on Y
             */
           
            // Calculate distance between center and projection on axe Y
            var distance_center_projection_y = Math.floor(distance_corner_center * Math.cos(Math.radians( delta_angle-90 )));
            
            // Create projection
            projection_y.x = Math.floor(center_x + distance_center_projection_y * Math.cos(Math.radians( -angle90 -90 ))); 
            projection_y.y =  Math.floor(center_y + distance_center_projection_y * Math.sin(Math.radians( -angle90 -90))); 
            
            // If is the min ? 
            if(projections.y.min == null
                || distance_center_projection_y < projections.y.min.distance){
            
                projections.y.min = projection_y;
                projections.y.min.distance = distance_center_projection_y;
                projections.y.min.corner = corner;
            }
            // Is the max ?
            if(projections.y.max == null
                || distance_center_projection_y > projections.y.max.distance){
            
                projections.y.max = projection_y;
                projections.y.max.distance = distance_center_projection_y;
                projections.y.max.corner = corner;
            }            
        }
        
        // Return object
        return projections;
    },
    
    is_approx_collide : function(){
        return (collide.FIXED_SQUARE_X + collide.FIXED_SQUARE_SIZE + collide.CURSOR_SQUARE_SIZE >= collide.cursor_x
            && collide.FIXED_SQUARE_Y + collide.FIXED_SQUARE_SIZE + collide.CURSOR_SQUARE_SIZE  >= collide.cursor_y
            && collide.FIXED_SQUARE_X <= collide.cursor_x + collide.FIXED_SQUARE_SIZE + collide.CURSOR_SQUARE_SIZE
            && collide.FIXED_SQUARE_Y <= collide.cursor_y + collide.FIXED_SQUARE_SIZE + collide.CURSOR_SQUARE_SIZE) ? true : false;
    },
    
    is_collide : function(){
        
        collide.fixed_projections.x.is_collide = 
                ( (collide.fixed_projections.x.min.distance <= -collide.CURSOR_SQUARE_SIZE/2 && collide.fixed_projections.x.max.distance >= -collide.CURSOR_SQUARE_SIZE/2 )
            ||  (collide.fixed_projections.x.min.distance <= collide.CURSOR_SQUARE_SIZE/2 && collide.fixed_projections.x.max.distance >= collide.CURSOR_SQUARE_SIZE/2 )
            ||  (collide.fixed_projections.x.min.distance >= -collide.CURSOR_SQUARE_SIZE/2 && collide.fixed_projections.x.max.distance <= collide.CURSOR_SQUARE_SIZE/2 )) ? true : false;
        collide.fixed_projections.y.is_collide = 
                ( (collide.fixed_projections.y.min.distance <= -collide.CURSOR_SQUARE_SIZE/2 && collide.fixed_projections.y.max.distance >= -collide.CURSOR_SQUARE_SIZE/2 )
            ||  (collide.fixed_projections.y.min.distance <= collide.CURSOR_SQUARE_SIZE/2 && collide.fixed_projections.y.max.distance >= collide.CURSOR_SQUARE_SIZE/2 )
            ||  (collide.fixed_projections.y.min.distance >= -collide.CURSOR_SQUARE_SIZE/2 && collide.fixed_projections.y.max.distance <= collide.CURSOR_SQUARE_SIZE/2 )) ? true : false;
        
        collide.cursor_projections.x.is_collide = 
                ( (collide.cursor_projections.x.min.distance <= -collide.FIXED_SQUARE_SIZE/2 && collide.cursor_projections.x.max.distance >= -collide.FIXED_SQUARE_SIZE/2 )
            ||  (collide.cursor_projections.x.min.distance <= collide.FIXED_SQUARE_SIZE/2 && collide.cursor_projections.x.max.distance >= collide.FIXED_SQUARE_SIZE/2 )
            ||  (collide.cursor_projections.x.min.distance >= -collide.FIXED_SQUARE_SIZE/2 && collide.cursor_projections.x.max.distance <= collide.FIXED_SQUARE_SIZE/2 )) ? true : false;
        collide.cursor_projections.y.is_collide = 
                ( (collide.cursor_projections.y.min.distance <= -collide.FIXED_SQUARE_SIZE/2 && collide.cursor_projections.y.max.distance >= -collide.FIXED_SQUARE_SIZE/2 )
            ||  (collide.cursor_projections.y.min.distance <= collide.FIXED_SQUARE_SIZE/2 && collide.cursor_projections.y.max.distance >= collide.FIXED_SQUARE_SIZE/2 )
            ||  (collide.cursor_projections.y.min.distance >= -collide.FIXED_SQUARE_SIZE/2 && collide.cursor_projections.y.max.distance <= collide.FIXED_SQUARE_SIZE/2 )) ? true : false;
        
        return (collide.fixed_projections.x.is_collide 
            && collide.fixed_projections.y.is_collide
            && collide.cursor_projections.x.is_collide
            && collide.cursor_projections.y.is_collide) ? true : false;
    }
    
};
$(document).ready(function(){
    collide.__init();
});



var debug = function(attr){
    if($('.debugjs').length == 0){
        $('<span class="debugjs"></span>').appendTo('body');
    }
    $('.debugjs').text(attr);
}
#collide {
  margin: 25px;
  border: 1px solid black;
  float: left;
}

#form {
  margin-left: 550px;
  padding-top: 2px;
}

#fixed_form h2 {
  color: #0033FF;
}

#cursor_form h2 {
  color: #FF8800;
}

#fixed_form input, #cursor_form input {
  margin-left: 25px;
  width: 50px;
}

#fixed_rotation_speed, #cursor_rotation_speed {
  margin-right: 150px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="collide" width="500" height="500"></canvas>


<div id="form">
  <h3>Understand how to detect if 2 rotates squares collide.</h3>
  <p>The 2 rotates squares collide only when all the projection of a square hit the second one.</p>
  <div id="fixed_form">
      <h2>Fixed square :</h2>
      Rotation speed : <input type="number" id="fixed_rotation_speed" value="0"/>
      Angle : <input type="number" id="fixed_angle" value="0"/>
      (Set : <input type="number" id="fixed_set_angle" value="0"/>)
  </div>
  <div id="cursor_form">
      <h2>Cursor square :</h2>
      Rotation speed : <input type="number" id="cursor_rotation_speed" value="-1"/>
      Angle : <input type="number" id="cursor_angle" value="0"/>
      (Set : <input type="number" id="cursor_set_angle" value="0"/>)
  </div>
</div>

Do the same job with no-rotate rect (it will be way easier) and it will work on every case

Community
  • 1
  • 1
Arthur
  • 4,870
  • 3
  • 32
  • 57
  • 4
    While this is a very pretty answer, and provides a theoretical basis for understanding the problem, if you're posting an answer and linking to code that solves the problem you should include that code in the question itself, in order that the question remains useful to others in the future should the external resource fall over, die or be otherwise reorganised. – David Thomas Dec 17 '16 at 17:29
  • Yeah i agree, but my code isn't an answer to the question :/ it's just a theorical example using a browser to understand the base of the problem. It's a lot's of old code not really usefull here – Arthur Dec 17 '16 at 17:31
  • 1
    If you could provide a concrete answer to the *specific* question asked (although generalising and abstracting the code would be welcome) I'm prepared to offer a bounty (though I have to wait a couple of days first) in response to the best answer simply out of personal interest and curiosity as to your approach realised in JavaScript (or jQuery, I suppose). :) – David Thomas Dec 17 '16 at 17:34
  • Updated to add the code on hidden snippet – Arthur Dec 17 '16 at 17:34
  • I can do that if you really want a final good answer for a specific problem. Do it working for rotated rect ? or just aligned ? – Arthur Dec 17 '16 at 17:36
  • That depends on the OP, really; I don't (currently) have a use for any particular answer to the problem, it really is just curiosity. But I'd suggest answering the question as posed, and then, if you wish to do so, extend it to make it more broadly useful to cover more general/abstract use-cases? – David Thomas Dec 17 '16 at 17:37
  • 2
    @Arthur — If you have answered it [__somewhere else__](http://stackoverflow.com/a/29614525/1746830), mark this post as dupe instead of pasting same solution here... IMO :) – Rayon Dec 17 '16 at 17:38
  • @Rayon, I asked myslef if the best was to link or rewrite, and finally i create another answer to update it to fit with the initial problem – Arthur Dec 17 '16 at 17:40
  • I also add a link to the original answer – Arthur Dec 17 '16 at 17:43
  • @DavidsaysreinstateMonica I still remembered about your request and finally do something (for you, but also for eveyone who'll more up to date solution). I also added the complete process in order to understand every step. https://stackoverflow.com/q/62028169/2929632 – Arthur May 26 '20 at 17:46
  • Your example and Code Pen are magnificent! – Garavani May 09 '23 at 05:38