Francis Hemsher Francis Hemsher - 20 days ago 6
Javascript Question

Create A Polygon From A Shape Created by Independent Lines

I have a group of 10 lines that have been arranged to create a shape. The lines are independent (not contiguous). I would like to build a polygon by finding the sequential points to build the polygon so it matches the shape. Any Ideas?

Example shown below:



<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Create Polygon From Lines</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body style='padding:10px;font-family:arial'>
<center>
<h4>Create Polygon From Lines</h4>
<div style='width:90%;background-color:gainsboro;text-align:justify;padding:10px;border-radius:6px;'>
A group of independent lines are connected to form a shape. Create a polygon that matches the shape.
</div>
<table><tr>
<td>
<div style="padding:10px;width:400px;text-align:justify">

<b>Scenerio:</b><br />
The shape is shown dashed:
Lines have been randomly placed and are not contiguous.<br>
We must arrange the points so a polygon can be drawn that matches the shape, i.e, the points must be sequential.
</div>
</td>
<td>
<div id="svgDiv" style='background-color:lightgreen;width:400px;height:400px;'>
<svg id="mySVG" width="400" height="400" overflow="visible">
<g id=lineG fill="none" stroke=black stroke-width=1 stroke-dasharray="4 4" />
<polygon id=myPolygon stroke='blue' fill='none' stroke-width='3' />
</svg>
</div>
</td>
</tr></table>
<script>
var Lines=[] //---[x1,y1,x2,y2]---
Lines[0]=[170, 148, 140, 200]
Lines[1]=[140, 200, 170, 251]
Lines[2]=[230, 251, 260, 200]
Lines[3]=[170, 148, 200, 96]
Lines[4]=[230, 251, 200, 303]
Lines[5]=[200, 303, 170, 251]
Lines[6]=[281, 118, 251, 66]
Lines[7]=[251, 66, 200, 96]
Lines[8]=[281, 118, 311, 170]
Lines[9]=[311, 170, 260, 200]

var NS="http://www.w3.org/2000/svg"
//---onLoad---
function placeLines()
{
for(var k=0;k<Lines.length;k++)
{
var line=document.createElementNS(NS,"line")
line.setAttribute("x1",Lines[k][0])
line.setAttribute("y1",Lines[k][1])
line.setAttribute("x2",Lines[k][2])
line.setAttribute("y2",Lines[k][3])
lineG.appendChild(line)
}
}

document.addEventListener("onload",placeLines(),false)

</script>
</body>
</html>




Answer

You can use a polygon with attribute points. In the example below, I just made a square but you can modify the points array to your needs...

Also note that I modified it to using array.map() - it is simpler that way than creating a variable, using that variable as an index in the array and then incrementing it after each iteration. For more info, read through these exercises.

<center>
<h4>Create Polygon From Lines</h4>
<div style='width:90%;background-color:gainsboro;text-align:justify;padding:10px;border-radius:6px;'>
A group of independent lines are connected to form a shape. Create a polygon that matches the shape.
</div>
<table><tr>
<td>
<div style="padding:10px;width:200px;text-align:justify">

<b>Scenerio:</b><br />
The shape is shown dashed:
Lines have been randomly placed and are not contiguous.<br>
We must arrange the points so a polygon can be drawn that matches the shape, i.e, the points must be sequential.
</div>
</td>
<td>
<div id="svgDiv" style='background-color:lightgreen;width:400px;height:400px;'>
<svg id="mySVG" width="400" height="400" overflow="visible">
<g id="shapeG" fill="none" stroke=black stroke-width=1 stroke-dasharray="4 4" />
<polygon id=myPolygon stroke='blue' fill='none' stroke-width='3' />
</svg>
</div>
</td>
</tr></table>
 <script>
var points=[  //figure out the points for your polygon
     [100, 100], // this is a simple square
     [200, 100],
     [200, 200],
     [100, 200]
];
var NS="http://www.w3.org/2000/svg"
//---onLoad---
function placeLines() {
    var polygon=document.createElementNS(NS,"polygon");

    var pointsAttribute = points.map(function(point) {
        return point[0]+' '+point[1];
    }).join(', ');
    polygon.setAttribute("points",pointsAttribute);
    document.getElementById('shapeG').appendChild(polygon);
}

document.addEventListener("onload",placeLines(),false)

</script>

Edit:

You asked how to compute the sequential points from the list of lines. I am not sure what the best way of doing this is, but one method would be to create a linked-list of points (which might also be considered a graph). Take a look at this example:

function Point(value) {
  this.value = value;
  this.next = null;
}
Point.prototype.SetNext = function(nextPoint) {
  this.next = nextPoint;
};

function PointList() {
  this.items = [];
}
PointList.prototype.addOrGet = function(value) {
  var foundPoint = this.items.find(function(item) {
    return item.value == value;
  });
  if (foundPoint) {
    return foundPoint;
  }
  //create new point
  var newPoint = new Point(value);
  this.items.push(newPoint);
  return newPoint;
};
PointList.prototype.GetPointsInOrder = function() {
  var current = this.items[0],
    next, nextPoints = [];
  for (var counter = 0; counter < this.items.length; counter++) {
    next = current.next;
    if (next) {
      nextPoints.push(next.value);
      current = next;
    }
  }
  return nextPoints.join(', ');
}

var Lines = [] //---[x1,y1,x2,y2]---
Lines[0] = [170, 148, 140, 200]
Lines[1] = [140, 200, 170, 251]
Lines[2] = [230, 251, 260, 200]
Lines[3] = [170, 148, 200, 96]
Lines[4] = [230, 251, 200, 303]
Lines[5] = [200, 303, 170, 251]
Lines[6] = [281, 118, 251, 66]
Lines[7] = [251, 66, 200, 96]
Lines[8] = [281, 118, 311, 170]
Lines[9] = [311, 170, 260, 200]

var NS = "http://www.w3.org/2000/svg"

function placeLines() {
  var placedLines = [];
  var polygon = document.createElementNS(NS, "polygon");
  var linePoints = [],
    point1, point2, indexOfPoint1, indexOfPoint2;
  var pointList = new PointList(),
    point1, point2, point1str, point2str;
  for (var k = 0; k < Lines.length; k++) {
    point1str = Lines[k][0] + ' ' + Lines[k][1];
    point2str = Lines[k][2] + ' ' + Lines[k][3];
    point1 = pointList.addOrGet(point1str);
    point2 = pointList.addOrGet(point2str);
    if (!point1.next) {
      point1.SetNext(point2);
    } else if (!point2.next) {
      point2.SetNext(point1);
    }
  }
  polygon.setAttribute("points", pointList.GetPointsInOrder());
  document.getElementById('lineG').appendChild(polygon);
}
document.addEventListener("onload", placeLines(), false);
<div id="svgDiv" style='background-color:lightgreen;width:400px;height:400px;'>
  <svg id="mySVG" width="400" height="400" overflow="visible">
    <g id=lineG fill="none" stroke=black stroke-width=1 stroke-dasharray="4 4" />
    <polygon id=myPolygon stroke='blue' fill='none' stroke-width='3' />
  </svg>
</div>

Comments