Permalink
Browse files

Support new shapeBufferDistance routing parameter.

This parameter can be used to automatically add a buffer space around
the edge of each shape when computing the obstacle size used for routing.
This allows you to specify true shape sizes to libavoid but prevent
connector paths from touching shapes.
  • Loading branch information...
1 parent c64d677 commit 35451d9e8ab66addcdfc49078cbb637f61cf076a @mjwybrow committed Aug 10, 2012
@@ -206,38 +206,29 @@ const Point& ReferencingPolygon::at(size_t index) const
}
-void PolygonInterface::getBoundingRect(double *minX, double *minY,
- double *maxX, double *maxY) const
+Box PolygonInterface::offsetBoundingBox(double offset) const
{
- double progressiveMinX = DBL_MAX;
- double progressiveMinY = DBL_MAX;
- double progressiveMaxX = -DBL_MAX;
- double progressiveMaxY = -DBL_MAX;
+ Box bBox;
+ bBox.min.x = DBL_MAX;
+ bBox.min.y = DBL_MAX;
+ bBox.max.x = -DBL_MAX;
+ bBox.max.y = -DBL_MAX;
for (size_t i = 0; i < size(); ++i)
{
- progressiveMinX = std::min(progressiveMinX, at(i).x);
- progressiveMinY = std::min(progressiveMinY, at(i).y);
- progressiveMaxX = std::max(progressiveMaxX, at(i).x);
- progressiveMaxY = std::max(progressiveMaxY, at(i).y);
+ bBox.min.x = std::min(bBox.min.x, at(i).x);
+ bBox.min.y = std::min(bBox.min.y, at(i).y);
+ bBox.max.x = std::max(bBox.max.x, at(i).x);
+ bBox.max.y = std::max(bBox.max.y, at(i).y);
}
- if (minX)
- {
- *minX = progressiveMinX;
- }
- if (maxX)
- {
- *maxX = progressiveMaxX;
- }
- if (minY)
- {
- *minY = progressiveMinY;
- }
- if (maxY)
- {
- *maxY = progressiveMaxY;
- }
+ // Add buffer space.
+ bBox.min.x -= offset;
+ bBox.min.y -= offset;
+ bBox.max.x += offset;
+ bBox.max.y += offset;
+
+ return bBox;
}
@@ -269,14 +260,88 @@ Polygon::Polygon(const PolygonInterface& poly)
}
-Polygon PolygonInterface::boundingRect(void) const
+Polygon PolygonInterface::boundingRectPolygon(void) const
{
- double minX, minY, maxX, maxY;
- getBoundingRect(&minX, &minY, &maxX, &maxY);
+ Box boundingBox = offsetBoundingBox(0.0);
- return Rectangle(Point(minX, minY), Point(maxX, maxY));
+ return Rectangle(boundingBox.min, boundingBox.max);
}
+static Point unitNormalForEdge(const Point &pt1, const Point &pt2)
+{
+ if (pt2 == pt1)
+ {
+ return Point(0, 0);
+ }
+ double dx = pt2.x - pt1.x;
+ double dy = pt2.y - pt1.y;
+ double f = 1.0 / std::sqrt((dx * dx) + (dy * dy));
+ dx *= f;
+ dy *= f;
+ return Point(dy, -dx);
+}
+
+Polygon PolygonInterface::offsetPolygon(double offset) const
+{
+ Polygon newPoly;
+ newPoly._id = id();
+ if (offset == 0)
+ {
+ for (size_t i = 0; i < size(); ++i)
+ {
+ newPoly.ps.push_back(at(i));
+ }
+ return newPoly;
+ }
+
+ size_t numOfEdges = size();
+ std::vector<Vector> normals(numOfEdges);
+ for (size_t i = 0; i < numOfEdges; ++i)
+ {
+ normals[i] = unitNormalForEdge(at(i), at((i + 1) % numOfEdges));
+ }
+
+ size_t j = numOfEdges - 1;
+ for (size_t i = 0; i < numOfEdges; ++i)
+ {
+ double R = 1 + ((normals[i].x * normals[j].x) +
+ (normals[i].y * normals[j].y));
+ if (((normals[j].x * normals[i].y) - (normals[i].x * normals[j].y)) *
+ offset >= 0)
+ {
+ double q = offset / R;
+ Point pt = Point(at(i).x + (normals[j].x + normals[i].x) * q,
+ at(i).y + (normals[j].y + normals[i].y) * q);
+
+ pt.id = id();
+ pt.vn = newPoly.size();
+ newPoly.ps.push_back(pt);
+ }
+ else
+ {
+ Point pt1 = Point(at(i).x + normals[j].x * offset,
+ at(i).y + normals[j].y * offset);
+ Point pt2 = at(i);
+ Point pt3 = Point(at(i).x + normals[i].x * offset,
+ at(i).y + normals[i].y * offset);
+
+ pt1.id = id();
+ pt1.vn = newPoly.size();
+ newPoly.ps.push_back(pt1);
+
+ pt2.id = id();
+ pt2.vn = newPoly.size();
+ newPoly.ps.push_back(pt2);
+
+ pt3.id = id();
+ pt3.vn = newPoly.size();
+ newPoly.ps.push_back(pt3);
+ }
+ j = i;
+ }
+
+ return newPoly;
+}
void Polygon::clear(void)
{
@@ -125,6 +125,19 @@ static const unsigned short kShapeConnectionPin = 9;
//!
typedef Point Vector;
+//! @brief A bounding box, represented by the top-left and
+//! bottom-right corners.
+//!
+class Box
+{
+ public:
+ //! The top-left point.
+ Point min;
+ //! The bottom-right point.
+ Point max;
+};
+
+
//! @brief A common interface used by the Polygon classes.
//!
@@ -146,21 +159,27 @@ class PolygonInterface
//! @brief Returns a specific point in the polygon.
//! @param[in] index The array index of the point to be returned.
virtual const Point& at(size_t index) const = 0;
- //! @brief Returns the bounding rectangle that contains this polygon.
+ //! @brief Returns the bounding rectangle for this polygon.
+ //!
+ //! @return A new Rectangle representing the bounding box.
+ Polygon boundingRectPolygon(void) const;
+ //! @brief Returns the bounding rectangle that contains this polygon
+ //! wtih optionally some buffer space around it for routing.
//!
//! If a NULL pointer is passed for any of the arguments, then that
//! value is ignored and not returned.
//!
+ //! If a buffer distance of zero is given, then this method returns
+ //! the bounding rectangle for the shape's polygon.
+ //!
+ //! @param offset Extra distance to pad each side of the rect.
//! @param[out] minX The left hand side of the bounding box.
//! @param[out] minY The top of the bounding box.
//! @param[out] maxX The right hand side of the bounding box.
//! @param[out] maxY The bottom of the bounding box.
- void getBoundingRect(double *minX, double *minY,
- double *maxX, double *maxY) const;
- //! @brief Returns the bounding rectangle for this polygon.
- //!
- //! @return A new Rectangle representing the bounding box.
- Polygon boundingRect(void) const;
+ Box offsetBoundingBox(double offset) const;
+
+ Polygon offsetPolygon(double offset) const;
};
@@ -176,12 +195,6 @@ class Edge
};
-//! @brief A bounding box, represented with an Edge between top-left and
-//! bottom-right corners.
-//!
-typedef Edge BBox;
-
-
class Router;
class ReferencingPolygon;
@@ -64,6 +64,7 @@ Rectangle JunctionRef::makeRectangle(Router *router, const Point& position)
COLA_ASSERT(router);
double nudgeDist = router->routingParameter(idealNudgingDistance);
+ nudgeDist = std::max(0.001, nudgeDist);
Point low = position;
low.x -= nudgeDist;
@@ -42,13 +42,14 @@ Obstacle::Obstacle(Router *router, Polygon ply, const unsigned int id)
m_id = m_router->assignId(id);
VertID i = VertID(m_id, 0);
-
+
+ Polygon routingPoly = routingPolygon();
const bool addToRouterNow = false;
VertInf *last = NULL;
VertInf *node = NULL;
- for (size_t pt_i = 0; pt_i < m_polygon.size(); ++pt_i)
+ for (size_t pt_i = 0; pt_i < routingPoly.size(); ++pt_i)
{
- node = new VertInf(m_router, i, m_polygon.ps[pt_i], addToRouterNow);
+ node = new VertInf(m_router, i, routingPoly.ps[pt_i], addToRouterNow);
if (!m_first_vert)
{
@@ -101,22 +102,23 @@ void Obstacle::setNewPoly(const Polygon& poly)
COLA_ASSERT(m_first_vert != NULL);
COLA_ASSERT(m_polygon.size() == poly.size());
+ m_polygon = poly;
+ Polygon routingPoly = routingPolygon();
+
VertInf *curr = m_first_vert;
- for (size_t pt_i = 0; pt_i < m_polygon.size(); ++pt_i)
+ for (size_t pt_i = 0; pt_i < routingPoly.size(); ++pt_i)
{
COLA_ASSERT(curr->visListSize == 0);
COLA_ASSERT(curr->invisListSize == 0);
// Reset with the new polygon point.
- curr->Reset(poly.ps[pt_i]);
+ curr->Reset(routingPoly.ps[pt_i]);
curr->pathNext = NULL;
curr = curr->shNext;
}
COLA_ASSERT(curr == m_first_vert);
- m_polygon = poly;
-
// It may be that the polygon for the obstacle has been updated after
// creating the shape. These events may have been combined for a single
// transaction, so update pin positions.
@@ -262,36 +264,33 @@ Router *Obstacle::router(void) const
}
-void Obstacle::boundingBox(BBox& bbox)
+Box Obstacle::routingBox(void) const
{
COLA_ASSERT(!m_polygon.empty());
+ COLA_ASSERT(m_router);
+
+ double bufferSpace = m_router->routingParameter(shapeBufferDistance);
+ return m_polygon.offsetBoundingBox(bufferSpace);
+}
- bbox.a = bbox.b = m_polygon.ps[0];
- Point& a = bbox.a;
- Point& b = bbox.b;
- for (size_t i = 1; i < m_polygon.size(); ++i)
- {
- const Point& p = m_polygon.ps[i];
+Polygon Obstacle::routingPolygon(void) const
+{
+ COLA_ASSERT(!m_polygon.empty());
+ COLA_ASSERT(m_router);
- a.x = std::min(p.x, a.x);
- a.y = std::min(p.y, a.y);
- b.x = std::max(p.x, b.x);
- b.y = std::max(p.y, b.y);
- }
+ double bufferSpace = m_router->routingParameter(shapeBufferDistance);
+ return m_polygon.offsetPolygon(bufferSpace);
}
Point Obstacle::shapeCentre(void)
{
- BBox bb;
- boundingBox(bb);
+ Box bb = routingBox();
Point centre;
-
- centre.x = bb.a.x + (0.5 * (bb.b.x - bb.a.x));
- centre.y = bb.a.y + (0.5 * (bb.b.y - bb.a.y));
-
+ centre.x = bb.min.x + (0.5 * (bb.max.x - bb.min.x));
+ centre.y = bb.min.y + (0.5 * (bb.max.y - bb.min.y));
return centre;
}
@@ -89,7 +89,8 @@ class Obstacle
void setNewPoly(const Polygon& poly);
VertInf *firstVert(void);
VertInf *lastVert(void);
- void boundingBox(BBox& bbox);
+ Box routingBox(void) const;
+ Polygon routingPolygon(void) const;
ConnRefList attachedConnectors(void) const;
private:
Oops, something went wrong.

0 comments on commit 35451d9

Please sign in to comment.