即使它们不应该相交的矩形

时间:2018-05-02 11:05:28

标签: fabricjs

如果我创建两个相邻的矩形并测试它们的交集,它总是返回true,即使它不应该。

从小提琴中可以看出,如果从x=0width=50px开始,第二个矩形需要从x=50开始,以避免介于两者之间。但是,为避免交叉,必须有2px的间隙。

为什么会这样,我该如何解决这个问题?



canvas = new fabric.Canvas('canvas');

// Starting at x=0
var rect1 = new fabric.Rect({
      left: 0, top: 0, fill: 'black', width: 50, height: 50, selectable: false,
    });

// Starting 50px right of the previous
var rect2 = new fabric.Rect({
      left: 50, top: 0, fill: 'blue', width: 50, height: 50, selectable: false,
    });

// Starting 51px right of the previous
var rect3 = new fabric.Rect({
      left: 101, top: 0, fill: 'black', width: 50, height: 50, selectable: false,
    });

// Starting 52px right of the previous
var rect4 = new fabric.Rect({
      left: 153, top: 0, fill: 'blue', width: 50, height: 50, selectable: false,
    });

canvas.add(rect1, rect2, rect3, rect4);

console.log(rect1.aCoords.tr, rect2.aCoords.tr, rect3.aCoords.tr, rect4.aCoords.tr);

if (rect1.intersectsWithObject(rect2))
    console.log("1st intersecting with 2nd.");
else
  console.log("No intersection between 1st and 2nd.");

if (rect2.intersectsWithObject(rect3))
    console.log("2nd intersecting with 3rd.");
else
  console.log("No intersection between 2nd and 3rd.");

if (rect3.intersectsWithObject(rect4))
    console.log("3rd intersecting with 4th.");
else
  console.log("No intersection between 3rd and 4th.");

<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.3/fabric.js"></script>
<p>Open console to see the rectangles absolute positions.</p>
<canvas id="canvas" width="300px" height="75px"></canvas>
&#13;
&#13;
&#13;

我的jsfiddle

3 个答案:

答案 0 :(得分:1)

我认为这是因为不可见的笔画宽度(默认为1)而发生的。

因此在矩形中,它们需要2px的间隙(左边为1px,右边为1px)。 我在你的样本上设置了笔划宽度为0px并再次运行测试。

canvas = new fabric.Canvas('canvas');

// Starting at x=0
var rect1 = new fabric.Rect({
      left: 0, top: 0, fill: 'black', width: 50, height: 50, selectable: false, strokeWidth: 0
    });

// Starting 50px right of the previous
var rect2 = new fabric.Rect({
      left: 51, top: 0, fill: 'blue', width: 50, height: 50, selectable: false, strokeWidth: 0
    });

// Starting 51px right of the previous
var rect3 = new fabric.Rect({
      left: 102, top: 0, fill: 'black', width: 50, height: 50, selectable: false, strokeWidth: 0
    });

// Starting 52px right of the previous
var rect4 = new fabric.Rect({
      left: 153, top: 0, fill: 'blue', width: 50, height: 50, selectable: false, strokeWidth: 0
    });

//canvas.add(rect1, rect2, rect3, rect4);
canvas.add(rect1);
canvas.add(rect2);
canvas.add(rect3);
canvas.add(rect4);

console.log(rect1.aCoords.tr, rect2.aCoords.tr, rect3.aCoords.tr, rect4.aCoords.tr);

if (rect1.intersectsWithObject(rect2))
    console.log("1st intersecting with 2nd.");
else
  console.log("No intersection between 1st and 2nd.");

if (rect2.intersectsWithObject(rect3))
    console.log("2nd intersecting with 3rd.");
else
  console.log("No intersection between 2nd and 3rd.");

if (rect3.intersectsWithObject(rect4))
    console.log("3rd intersecting with 4th.");
else
  console.log("No intersection between 3rd and 4th.");
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.3/fabric.min.js"></script>
<p>Open console to see the rectangles absolute positions.</p>
<canvas id="canvas" width="300px" height="75px"></canvas>

选中fiddle

答案 1 :(得分:1)

我通过使用Fabric.js的低级函数解决了这个问题。如果找到了一个交叉点,我会检查是否只有一个交叉点,以及该点是否是我们其中一个对象的一个​​角。如果是真的,我们有一个假的交叉点&#34;。

&#13;
&#13;
    function isIntersecting(obj1, obj2) {
  var result = new fabric.Intersection(),
	points1 = obj1.getCoords(true, false),
	points2 = obj2.getCoords(true, false),
	length1 = points1.length,
	length2 = points2.length,
	a1, a2, b1, b2;
      
  // Check if one object lies within the other.
  if (obj1.isContainedWithinObject(obj2, false, true) || obj2.isContainedWithinObject(obj1, false, true))
  	return true;
  
  // Check for intersection between all edges.
  for (var i = 0; i < length1; i++) {
        a1 = points1[i];
        a2 = points1[(i + 1) % length1];
      
      for (var j = 0; j < length2; j++) {
        b1 = points2[j];
        b2 = points2[(j + 1) % length2];
      	result = fabric.Intersection.intersectLineLine(a1, a2, b1, b2);
        
        if (result.status == 'Intersection') {
          // It's not an intersection if we have only 1 intersection point and if this one is the end of one of our lines.
          let allPoints = [a1, a2, b1, b2];
          if (result.points.length > 1 || !polygonIncludesPoint(allPoints, result.points[0])) {
          	return true;
          }
          else if (obj2.containsPoint(a1) || obj2.containsPoint(a2)	||
          		obj1.containsPoint(b1) || obj1.containsPoint(b2)) {
          	// But it is if one corner of an edge is within the other object.	
            return true;
          }
        }
      }
  }
  
  return false;
}

function polygonIncludesPoint(points, point) {
  for (var i = 0; i < points.length; i++) {
        if (points[i].eq(point))
    	  return true;
  }
  return false;
}

var canvas = new fabric.Canvas('canvas');

var center = new fabric.Rect({
      left: 50, top: 50, fill: 'black', width: 50, height: 50, selectable: false, strokeWidth: 0
    });

var tl = new fabric.Rect({
      left: 0, top: 0, fill: 'blue', width: 50, height: 50, selectable: false, strokeWidth: 0
    });

var tm = new fabric.Rect({
      left: 50, top: 0, fill: 'grey', width: 50, height: 50, selectable: false, strokeWidth: 0
    });

var tr = new fabric.Rect({
      left: 100, top: 0, fill: 'blue', width: 50, height: 50, selectable: false, strokeWidth: 0
    });
    
var ml = new fabric.Rect({
      left: 0, top: 50, fill: 'grey', width: 50, height: 50, selectable: false, strokeWidth: 0
    });
    
var mr = new fabric.Rect({
      left: 100, top: 50, fill: 'grey', width: 50, height: 50, selectable: false, strokeWidth: 0
    });
    
var bl = new fabric.Rect({
      left: 0, top: 100, fill: 'blue', width: 50, height: 50, selectable: false, strokeWidth: 0
    });
    
var bm = new fabric.Rect({
      left: 50, top: 100, fill: 'grey', width: 50, height: 50, selectable: false, strokeWidth: 0
    });
    
var br = new fabric.Rect({
      left: 80, top: 80, fill: 'blue', width: 50, height: 50, selectable: false, strokeWidth: 0
    });
    
var center2 = new fabric.Rect({
      left: 180, top: 20, fill: 'black', width: 50, height: 50, selectable: false, strokeWidth: 0
    });
    
var bigRect = new fabric.Rect({
      left: 180, top: 20, fill: 'rgba(0, 0, 255, 0.3)', width: 90, height: 90, selectable: false, strokeWidth: 0
    });
    
var center3 = new fabric.Rect({
      left: 310, top: 40, fill: 'black', width: 50, height: 50, selectable: false, strokeWidth: 0
    });
    
var bigRect2 = new fabric.Rect({
      left: 290, top: 20, fill: 'rgba(0, 0, 255, 0.3)', width: 90, height: 90, selectable: false, strokeWidth: 0
    });
    
    

canvas.add(center, tl, tm, tr, ml, mr, bl, bm, br, center2, bigRect, center3, bigRect2);

var objects = canvas.getObjects('rect');

// Check 1st case
console.log("1st case:");
objects.forEach(function (targ) {
  if (targ === center || targ === center2 || targ === bigRect || targ === center3 || targ === bigRect2) return;

  if (isIntersecting(center, targ))
  	console.log("Intersection");
  else
  	console.log("No intersection");
});

// Check 2nd case
console.log("2nd case:");
if (isIntersecting(center2, bigRect))
	console.log("Intersection");
else
  console.log("No intersection");
  
// Check 3rd case
console.log("3rd case");
if (isIntersecting(center3, bigRect2))
	console.log("Intersection");
else
	console.log("No intersection");
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.3/fabric.min.js"></script>
<p>See console for results.</p>
<canvas id="canvas" width="400px" height="200px"></canvas>
&#13;
&#13;
&#13;

我的jsfiddle

答案 2 :(得分:1)

@Durga集中了这一点,中风正在创造交叉点。

要添加更多细节,您应该考虑路径而不是像素。

宽50且从0开始的矩形实际上与另一个从50开始的矩形交叉,考虑它们的边完全重叠,两个镜之间没有空间,它们相互接触。

我同意可以添加一个参数,以便在返回布尔值时不考虑重叠。