5

I am rendering SVG image dynamically and created rotated text. If the rotated text is overlap with other text, i need to remove that text. But i can't measure the rotated text to create bounds and check with next label text region.

I have created 3 SVG element to explain.

  1. SVG-1 Shows the overlapped text.
  2. SVG-2 Shows the rotated text with overlapped (Angle-10)
  3. SVG-3 Shows the rotated text without overlapping (Angle-50)

I will rotate the text to any angle dynamically. If it is overlapped while rotating text, I need to remove that overlapped text programmatically .

Fiddle link

<div style=" width: 150px;height: 150px;">

  <svg style="width: 250px; height: 144px; border: solid black 1px;">
    <text id="XLabel_0" x="75" y="30">Sprint 13_March_2015</text>
    <text id="XLabel_1" x="100" y="30">DT_Apr2015_Sprint13</text>
  </svg>

  <svg style="width: 250px; height: 144px; border: solid black 1px;">
    <text id="Label_0" x="75" y="30" transform="rotate(10, 75, 34.5)">Sprint 13_March_2015</text>
    <text id="XLabel_1" x="100" y="30" transform="rotate(10, 100, 34.5)">DT_Apr2015_Sprint13</text>
  </svg>

  <svg style="width: 250px; height: 144px; border:solid black 1px;">
    <text id="XLabel_0" x="75" y="30" transform="rotate(50,94,34.5)">Sprint 13_March_2015</text>
    <text id="XLabel_1" x="100" y="30" transform="rotate(50,123,61)" >DT_Apr2015_Sprint13</text>
  </svg>
  
</div>

Can anyone suggest a solution?

Robin Mackenzie
  • 18,801
  • 7
  • 38
  • 56
Bharathi
  • 1,288
  • 2
  • 14
  • 40
  • Why can't you measure the rotate text? What's wrong with getBBox or getBoundingClientRect? – Robert Longson Mar 20 '17 at 10:41
  • If I use the getBoundingClientRect Means, SVG-3 2'nd text will be removed. Because first text (x+width) region overlapped with 2'nd text x position. Please refer the fiddle last SVG output – Bharathi Mar 20 '17 at 10:44
  • Please show what you're doing, there's no javascript in your code. – Robert Longson Mar 20 '17 at 10:57
  • Also, are you actually trying to find out if rotated text overlaps. Or are you trying to find an appropriate angle to rotate some text so that it doesn't overlap? If the latter, then it would probably be better to ask that question instead. – Paul LeBeau Mar 20 '17 at 13:34

1 Answers1

5

It can be kinda tricky, but you can compute polygons for each text element, and then see if they intersect. I used one of your labels in the example below:

<!DOCTYPE HTML>
<html>

<body>
  <svg style="width: 250px; height: 144px; border: solid black 1px;">
    <text id="label1" x="75" y="30" transform="rotate(10, 75, 34.5)">Sprint 13_March_2015</text>
    <text id="label2" x="100" y="30" transform="rotate(10, 100, 34.5)">DT_Apr2015_Sprint13</text>
    <polygon id=polygon1 fill="none" stroke="blue" stroke-dasharray="5 5" stroke-width=1 />
    <polygon id=polygon2 fill="none" stroke="red" stroke-dasharray="5 5" stroke-width=1 />
  </svg>
<br>
<button onClick=testOverlap()>Test Overlap</button>
<script>
function testOverlap()
{
    //---show 'native' rects---
    var trns1=label1.getAttribute("transform")
    label1.removeAttribute("transform")
    var bb1=label1.getBBox()
    var bb1x=bb1.x
    var bb1y=bb1.y
    var bb1w=bb1.width
    var bb1h=bb1.height
    label1.setAttribute("transform",trns1)

    var pnts1=[bb1x,bb1y,bb1x,bb1y+bb1h,bb1x+bb1w,bb1y+bb1h,bb1x+bb1w,bb1y]
    polygon1.setAttribute("points",pnts1.join())
    polygon1.setAttribute("transform",trns1)
    //---remove transform from polygon--
    ctmPolygon(polygon1)


    var trns2=label2.getAttribute("transform")
    label2.removeAttribute("transform")
    var bb2=label2.getBBox()
    var bb2x=bb2.x
    var bb2y=bb2.y
    var bb2w=bb2.width
    var bb2h=bb2.height

    label2.setAttribute("transform",trns2)
    var pnts2=[bb2x,bb2y,bb2x,bb2y+bb2h,bb2x+bb2w,bb2y+bb2h,bb2x+bb2w,bb2y]
    polygon2.setAttribute("points",pnts2.join())
    polygon2.setAttribute("transform",trns2)
     //---remove transform from polygon--
    ctmPolygon(polygon2)


    alert(getPolygonIntersect(polygon1,polygon2))

}
//---screen points for polygon---
function ctmPolygon(myPoly)
{
 var ctm = myPoly.getCTM()
 var svgRoot = myPoly.ownerSVGElement

 var pointsList = myPoly.points;
 var n = pointsList.numberOfItems;


 for(var m=0; m < n; m++)
 {
  var mySVGPoint = svgRoot.createSVGPoint();
  mySVGPoint.x = pointsList.getItem(m).x
  mySVGPoint.y = pointsList.getItem(m).y
  mySVGPointTrans = mySVGPoint.matrixTransform(ctm)
  pointsList.getItem(m).x=mySVGPointTrans.x
  pointsList.getItem(m).y=mySVGPointTrans.y
 };

 myPoly.removeAttribute("transform")
}
function getPolygonIntersect(polygonA,polygonB)
{
 var IntPoints=[]
 var aPoints=polygonA.points
 var m=aPoints.numberOfItems
 for(var i=0;i<m;i++)
 {
  var aX1=aPoints.getItem(i).x
  var aY1=aPoints.getItem(i).y

  if(i<m-1)
  {
   var aX2=aPoints.getItem(i+1).x
   var aY2=aPoints.getItem(i+1).y
  }
  else
  {
   var aX2=aPoints.getItem(0).x
   var aY2=aPoints.getItem(0).y
  }

  var bPoints=polygonB.points
  var n=bPoints.numberOfItems

  for(var k=0;k<n;k++) //--each side of polygon---
  {
   var bX1=bPoints.getItem(k).x
   var bY1=bPoints.getItem(k).y

   if(k<n-1)
   {
    var bX2=bPoints.getItem(k+1).x
    var bY2=bPoints.getItem(k+1).y
   }
   else
   {
    var bX2=bPoints.getItem(0).x
    var bY2=bPoints.getItem(0).y
   }
   //---return false or intersect point---
   var xy=lineSegIntersect(aX1,aY1,aX2,aY2,bX1,bY1,bX2,bY2)
   if(xy)
   {
    if(IntPoints.join().indexOf(xy)==-1)//--no dups--
    {
     IntPoints.push(xy)
    }

   }
  }
 }
    if(IntPoints.length>0)
        return true
    else
        return false
}
//---compare two lines: A.B---
function lineSegIntersect(aX1,aY1,aX2,aY2,bX1,bY1,bX2,bY2)
{
 //---compute vectors Va, Vb--------
 var Va=( (bX2-bX1)*(aY1-bY1) - (bY2-bY1)*(aX1-bX1) )/ ( (bY2-bY1)*(aX2-aX1) - (bX2-bX1)*(aY2-aY1) )
 var Vb=( (aX2-aX1)*(aY1-bY1) - (aY2-aY1)*(aX1-bX1) )/( (bY2-bY1)*(aX2-aX1) - (bX2-bX1)*(aY2-aY1) )

 if(Va>0 && Va<1 && Vb>0 && Vb<1)
 {
 //---intersect true, show point---
  var ma=(aY2-aY1)/(aX2-aX1)
  var mb=(bY2-bY1)/(bX2-bX1)
  if(aX2!=aX1&&bX2!=bX1) //---!vertical line---
  {
   var x=(aX1*ma-aY1-bX1*mb+bY1)/(ma-mb)
   var y=ma*(x-aX1)+aY1
  }
  else if(aX2==aX1)
  {
   var x=aX1
   var y=mb*(x-bX1)+bY1
  }
  else if(bX2==bX1)
  {
   var x=bX1
   var y=ma*(x-aX1)+aY1
  }

  return [x,y]
    }
 else
 return false
}

</script>
</body>

</html>
Francis Hemsher
  • 3,478
  • 2
  • 13
  • 15