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 < routingPoly.size(); ++pt_i) { COLA_ASSERT(curr->visListSize == 0); COLA_ASSERT(curr->invisListSize == 0); // Reset with the new polygon point. curr->Reset(routingPoly.ps[pt_i]); curr->pathNext = NULL; curr = curr->shNext; } COLA_ASSERT(curr == m_first_vert); // 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. for (ShapeConnectionPinSet::iterator curr = m_connection_pins.begin(); curr != m_connection_pins.end(); ++curr) { ShapeConnectionPin *pin = *curr; pin->updatePosition(m_polygon); } }
void JunctionRef::setPositionFixed(bool fixed) { m_position_fixed = fixed; // Remove existing connection pins. while ( ! m_connection_pins.empty() ) { delete *(m_connection_pins.begin()); } if (m_position_fixed) { // Set up pins in four directions, each exclusive. m_connection_pins.insert(new Avoid::ShapeConnectionPin(this, Avoid::CONNECTIONPIN_CENTRE, ConnDirUp)); m_connection_pins.insert(new Avoid::ShapeConnectionPin(this, Avoid::CONNECTIONPIN_CENTRE, ConnDirDown)); m_connection_pins.insert(new Avoid::ShapeConnectionPin(this, Avoid::CONNECTIONPIN_CENTRE, ConnDirLeft)); m_connection_pins.insert(new Avoid::ShapeConnectionPin(this, Avoid::CONNECTIONPIN_CENTRE, ConnDirRight)); } else { // For non-fixed Junctions, use a single non-excluusive pin. ShapeConnectionPin *pin = new Avoid::ShapeConnectionPin(this, Avoid::CONNECTIONPIN_CENTRE, ConnDirAll); pin->setExclusive(false); m_connection_pins.insert(pin); } }
int main(void) { Router *router = new Router(OrthogonalRouting); router->setRoutingPenalty((PenaltyType)0, 50); router->setRoutingPenalty((PenaltyType)1, 0); router->setRoutingPenalty((PenaltyType)2, 0); router->setRoutingPenalty((PenaltyType)3, 4000); router->setRoutingPenalty((PenaltyType)4, 105); router->setOrthogonalNudgeDistance(25); Rectangle rect478845150(Point(50695, 51070), Point(50705, 51080)); ShapeRef *shapeRef478845150 = new ShapeRef(router, rect478845150, 478845150); ShapeConnectionPin *pin = new Avoid::ShapeConnectionPin(shapeRef478845150, Avoid::CONNECTIONPIN_CENTRE, Avoid::ATTACH_POS_CENTRE, Avoid::ATTACH_POS_CENTRE); pin->setExclusive(false); router->addShape(shapeRef478845150); Rectangle rect92712048(Point(51246, 50475), Point(51304, 50585)); ShapeRef *shapeRef92712048 = new ShapeRef(router, rect92712048, 92712048); router->addShape(shapeRef92712048); Rectangle rect23127921(Point(50365, 50766), Point(50485, 50834)); ShapeRef *shapeRef23127921 = new ShapeRef(router, rect23127921, 23127921); router->addShape(shapeRef23127921); Rectangle rect159957148(Point(51740, 50891), Point(51860, 50959)); ShapeRef *shapeRef159957148 = new ShapeRef(router, rect159957148, 159957148); router->addShape(shapeRef159957148); Rectangle rect1350214(Point(50375, 51015), Point(50625, 51135)); ShapeRef *shapeRef1350214 = new ShapeRef(router, rect1350214, 1350214); router->addShape(shapeRef1350214); Rectangle rect247197258(Point(50265, 51046), Point(50375, 51104)); ShapeRef *shapeRef247197258 = new ShapeRef(router, rect247197258, 247197258); router->addShape(shapeRef247197258); Rectangle rect281096654(Point(50700, 50390), Point(51000, 50610)); ShapeRef *shapeRef281096654 = new ShapeRef(router, rect281096654, 281096654); router->addShape(shapeRef281096654); ConnEnd srcPt342420237(Point(50425, 50800), 15); ConnEnd dstPt342420237(Point(50710, 50450), 4); new ConnRef(router, srcPt342420237, dstPt342420237, 342420237); ConnEnd srcPt352019675(Point(50990, 50500), 8); ConnEnd dstPt352019675(shapeRef478845150, Avoid::CONNECTIONPIN_CENTRE); //ConnEnd dstPt352019675(Point(50700, 51075), 15); new ConnRef(router, srcPt352019675, dstPt352019675, 352019675); ConnEnd srcPt42699400(shapeRef478845150, Avoid::CONNECTIONPIN_CENTRE); //ConnEnd srcPt42699400(Point(50700, 51075), 15); ConnEnd dstPt42699400(Point(50615, 51075), 8); new ConnRef(router, srcPt42699400, dstPt42699400, 42699400); ConnEnd srcPt94712625(Point(50710, 50550), 4); ConnEnd dstPt94712625(shapeRef478845150, Avoid::CONNECTIONPIN_CENTRE); //ConnEnd dstPt94712625(Point(50700, 51075), 15); new ConnRef(router, srcPt94712625, dstPt94712625, 94712625); ConnEnd srcPt92802970(Point(50990, 50450), 8); ConnEnd dstPt92802970(Point(51275, 50485), 1); new ConnRef(router, srcPt92802970, dstPt92802970, 92802970); ConnEnd srcPt716502036(Point(50710, 50500), 4); ConnEnd dstPt716502036(Point(51800, 50925), 15); new ConnRef(router, srcPt716502036, dstPt716502036, 716502036); router->processTransaction(); router->outputInstanceToSVG("test-junction01"); delete router; return 0; };
JunctionRef::JunctionRef(Router *router, Point position, const unsigned int id) : Obstacle(router, makeRectangle(router, position), id), m_position(position), m_recommended_position(position), m_position_fixed(false) { // For Junctions we use a single non-exclusive pin. ShapeConnectionPin *pin = new Avoid::ShapeConnectionPin(this, Avoid::CONNECTIONPIN_CENTRE, ConnDirAll); pin->setExclusive(false); m_connection_pins.insert(pin); m_router->addJunction(this); }
bool ShapeConnectionPin::operator==(const ShapeConnectionPin& rhs) const { COLA_ASSERT(m_router == rhs.m_router); if (containingObjectId() != rhs.containingObjectId()) { return false; } // The shape/junction is equal, so examine the unique members. if (m_class_id != rhs.m_class_id) { return false; } if (m_visibility_directions != rhs.m_visibility_directions) { return false; } if (m_x_portion_offset != rhs.m_x_portion_offset) { return false; } if (m_y_portion_offset != rhs.m_y_portion_offset) { return false; } if (m_inside_offset != rhs.m_inside_offset) { return false; } return true; }
void JunctionRef::moveAttachedConns(const Point& newPosition) { // Update positions of attached connector ends. for (std::set<ConnEnd *>::iterator curr = m_following_conns.begin(); curr != m_following_conns.end(); ++curr) { ConnEnd *connEnd = *curr; COLA_ASSERT(connEnd->m_conn_ref != NULL); m_router->modifyConnector(connEnd->m_conn_ref, connEnd->endpointType(), *connEnd); } for (ShapeConnectionPinSet::iterator curr = m_connection_pins.begin(); curr != m_connection_pins.end(); ++curr) { ShapeConnectionPin *pin = *curr; pin->updatePosition(newPosition); } }
bool ShapeConnectionPin::operator<(const ShapeConnectionPin& rhs) const { COLA_ASSERT(m_router == rhs.m_router); if (containingObjectId() != rhs.containingObjectId()) { return containingObjectId() < rhs.containingObjectId(); } // Note: operator< is used for set ordering within each shape or junction, // so the m_shape/m_junction values should match and we needn't perform the // above test in most cases and could just assert the following: // COLA_ASSERT(m_shape == rhs.m_shape); // COLA_ASSERT(m_junction == rhs.m_junction); if (m_class_id != rhs.m_class_id) { return m_class_id < rhs.m_class_id; } if (m_visibility_directions != rhs.m_visibility_directions) { return m_visibility_directions < rhs.m_visibility_directions; } if (m_x_portion_offset != rhs.m_x_portion_offset) { return m_x_portion_offset < rhs.m_x_portion_offset; } if (m_y_portion_offset != rhs.m_y_portion_offset) { return m_y_portion_offset < rhs.m_y_portion_offset; } if (m_inside_offset != rhs.m_inside_offset) { return m_inside_offset < rhs.m_inside_offset; } // Otherwise, they are considered the same. return false; }
void JunctionRef::preferOrthogonalDimension(const size_t dim) { const double smallPenalty = 1.0; for (ShapeConnectionPinSet::iterator curr = m_connection_pins.begin(); curr != m_connection_pins.end(); ++curr) { ShapeConnectionPin *pin = *curr; if (dim == YDIM) { if (pin->directions() & (ConnDirLeft | ConnDirRight)) { pin->setConnectionCost(smallPenalty); } } else if (dim == XDIM) { if (pin->directions() & (ConnDirUp | ConnDirDown)) { pin->setConnectionCost(smallPenalty); } } } }
// Assign visibility to a dummy vertex representing all the possible pins // for this pinClassId. void ConnEnd::assignPinVisibilityTo(VertInf *dummyConnectionVert, VertInf *targetVert) { unsigned int validPinCount = 0; COLA_ASSERT(m_anchor_obj); COLA_ASSERT(m_connection_pin_class_id != CONNECTIONPIN_UNSET); Router *router = m_anchor_obj->router(); for (ShapeConnectionPinSet::iterator curr = m_anchor_obj->m_connection_pins.begin(); curr != m_anchor_obj->m_connection_pins.end(); ++curr) { ShapeConnectionPin *currPin = *curr; if ((currPin->m_class_id == m_connection_pin_class_id) && (!currPin->m_exclusive || currPin->m_connend_users.empty())) { double routingCost = currPin->m_connection_cost; Point adjTargetPt = targetVert->point - currPin->m_vertex->point; double angle = rotationalAngle(adjTargetPt); bool inVisibilityRange = false; if (angle <= 45 || angle >= 315) { if (currPin->directions() & ConnDirRight) { inVisibilityRange = true; } } if (angle >= 45 && angle <= 135) { if (currPin->directions() & ConnDirDown) { inVisibilityRange = true; } } if (angle >= 135 && angle <= 225) { if (currPin->directions() & ConnDirLeft) { inVisibilityRange = true; } } if (angle >= 225 && angle <= 315) { if (currPin->directions() & ConnDirUp) { inVisibilityRange = true; } } if (!inVisibilityRange) { routingCost += router->routingParameter(portDirectionPenalty); } if (router->m_allows_orthogonal_routing) { // This has same ID and is either unconnected or not // exclusive, so give it visibility. EdgeInf *edge = new EdgeInf(dummyConnectionVert, currPin->m_vertex, true); // XXX Can't use a zero cost due to assumptions // elsewhere in code. edge->setDist(manhattanDist(dummyConnectionVert->point, currPin->m_vertex->point) + std::max(0.001, routingCost)); } if (router->m_allows_orthogonal_routing) { // This has same ID and is either unconnected or not // exclusive, so give it visibility. EdgeInf *edge = new EdgeInf(dummyConnectionVert, currPin->m_vertex, false); // XXX Can't use a zero cost due to assumptions // elsewhere in code. edge->setDist(euclideanDist(dummyConnectionVert->point, currPin->m_vertex->point) + std::max(0.001, routingCost)); } // Increment the number of valid pins for this ConnEnd connection. validPinCount++; } } if (validPinCount == 0) { // There should be at least one pin, otherwise we will have // problems finding connector routes. err_printf("Warning: In ConnEnd::assignPinVisibilityTo():\n" " ConnEnd for connector %d can't connect to shape %d\n" " since it has no pins with class id of %u.\n", (int) m_conn_ref->id(), (int) m_anchor_obj->id(), m_connection_pin_class_id); } }
void ShapeRef::transformConnectionPinPositions( ShapeTransformationType transform) { for (ShapeConnectionPinSet::iterator curr = m_connection_pins.begin(); curr != m_connection_pins.end(); ++curr) { ShapeConnectionPin *pin = *curr; double& xPortionOffset = pin->m_x_portion_offset; double& yPortionOffset = pin->m_y_portion_offset; ConnDirFlags& visDirs = pin->m_visibility_directions; double tmpOffset; // Translate to Origin. xPortionOffset -= 0.5; yPortionOffset -= 0.5; // Number of clockwise 90degree rotations; unsigned int rotationN = 0; switch (transform) { case TransformationType_CW90: rotationN = 3; // Y <- inverse X, X <- inverse Y tmpOffset = yPortionOffset; yPortionOffset = xPortionOffset; xPortionOffset = -tmpOffset; break; case TransformationType_CW180: rotationN = 2; // Y <- inverse Y, X <- inverse X yPortionOffset = -yPortionOffset; xPortionOffset = -xPortionOffset; break; case TransformationType_CW270: rotationN = 1; // Y <- X, X <- Y tmpOffset = yPortionOffset; yPortionOffset = -xPortionOffset; xPortionOffset = tmpOffset; break; case TransformationType_FlipX: // Y <- Y, X <- inverse X xPortionOffset = -xPortionOffset; break; case TransformationType_FlipY: // X <- inverse X, Y <- Y yPortionOffset = -yPortionOffset; break; } // Translate back. xPortionOffset += 0.5; yPortionOffset += 0.5; if ( (visDirs & ConnDirAll) && (visDirs != ConnDirAll) ) { // Visibility is set, but not in all directions. const unsigned int dirU = 0; const unsigned int dirR = 1; const unsigned int dirD = 2; const unsigned int dirL = 3; bool visInDir[4] = { false }; if (visDirs & ConnDirUp) visInDir[dirU] = true; if (visDirs & ConnDirRight) visInDir[dirR] = true; if (visDirs & ConnDirDown) visInDir[dirD] = true; if (visDirs & ConnDirLeft) visInDir[dirL] = true; if (transform == TransformationType_FlipY) { bool tmpBool = visInDir[dirU]; visInDir[dirU] = visInDir[dirD]; visInDir[dirD] = tmpBool; } else if (transform == TransformationType_FlipX) { bool tmpBool = visInDir[dirL]; visInDir[dirL] = visInDir[dirR]; visInDir[dirR] = tmpBool; } visDirs = ConnDirNone; if (visInDir[(rotationN + dirU) % 4]) visDirs |= ConnDirUp; if (visInDir[(rotationN + dirR) % 4]) visDirs |= ConnDirRight; if (visInDir[(rotationN + dirD) % 4]) visDirs |= ConnDirDown; if (visInDir[(rotationN + dirL) % 4]) visDirs |= ConnDirLeft; } pin->updatePositionAndVisibility(); m_router->modifyConnectionPin(pin); } }
int main(void) { Router *router = new Router(OrthogonalRouting); router->setRoutingParameter((RoutingParameter)0, 2); router->setRoutingParameter((RoutingParameter)1, 0); router->setRoutingParameter((RoutingParameter)2, 0); router->setRoutingParameter((RoutingParameter)3, 4000); router->setRoutingParameter((RoutingParameter)4, 9000); router->setRoutingParameter((RoutingParameter)5, 0); router->setRoutingParameter((RoutingParameter)6, 0); router->setRoutingParameter((RoutingParameter)7, 16); router->setRoutingParameter((RoutingParameter)8, 0); router->setRoutingOption((RoutingOption)0, false); router->setRoutingOption((RoutingOption)1, true); router->setRoutingOption((RoutingOption)2, false); router->setRoutingOption((RoutingOption)3, false); router->setRoutingOption((RoutingOption)4, true); router->setRoutingOption((RoutingOption)5, false); router->setRoutingOption((RoutingOption)6, true); Polygon polygon; ConnEnd srcPt; ConnEnd dstPt; ConnEnd heConnPt; PolyLine newRoute; ShapeConnectionPin *connPin = NULL; // shapeRef1 polygon = Polygon(4); polygon.ps[0] = Point(450, 330); polygon.ps[1] = Point(490, 330); polygon.ps[2] = Point(490, 450); polygon.ps[3] = Point(450, 450); ShapeRef *shapeRef1 = new ShapeRef(router, polygon, 1); connPin = new ShapeConnectionPin(shapeRef1, 1, 0, 0.333333, true, 10, (ConnDirFlags) 0); connPin->setExclusive(false); connPin = new ShapeConnectionPin(shapeRef1, 2, 0, 0.666667, true, 10, (ConnDirFlags) 0); connPin->setExclusive(false); connPin = new ShapeConnectionPin(shapeRef1, 3, 1, 0.5, true, 10, (ConnDirFlags) 0); connPin->setExclusive(false); connPin = new ShapeConnectionPin(shapeRef1, 4, 0.5, 0, true, 10, (ConnDirFlags) 0); connPin->setExclusive(false); // shapeRef8 polygon = Polygon(4); polygon.ps[0] = Point(502, 237.5); polygon.ps[1] = Point(502, 262.5); polygon.ps[2] = Point(438, 262.5); polygon.ps[3] = Point(438, 237.5); ShapeRef *shapeRef8 = new ShapeRef(router, polygon, 8); connPin = new ShapeConnectionPin(shapeRef8, 1, 0, 0.5, true, 1, (ConnDirFlags) 0); connPin = new ShapeConnectionPin(shapeRef8, 2, 1, 0.5, true, 1, (ConnDirFlags) 0); connPin = new ShapeConnectionPin(shapeRef8, 3, 0.5, 1, true, 1, (ConnDirFlags) 0); connPin = new ShapeConnectionPin(shapeRef8, 4, 0.5, 0, true, 1, (ConnDirFlags) 0); JunctionRef *junctionRef6 = new JunctionRef(router, Point(470, 300), 6); /* // This may be useful if junction pins are modified. connPin = new ShapeConnectionPin(junctionRef6, 2147483646, (ConnDirFlags) 15); */ // connRef9 ConnRef *connRef9 = new ConnRef(router, 9); srcPt = ConnEnd(junctionRef6); connRef9->setSourceEndpoint(srcPt); dstPt = ConnEnd(shapeRef8, 3); connRef9->setDestEndpoint(dstPt); connRef9->setRoutingType((ConnType)2); #if 1 // connRef10 - WITH BUG ConnRef *connRef10 = new ConnRef(router, 10); srcPt = ConnEnd(junctionRef6); connRef10->setSourceEndpoint(srcPt); dstPt = ConnEnd(shapeRef1, 4); connRef10->setDestEndpoint(dstPt); connRef10->setRoutingType((ConnType)2); #else // connRef10 - WITHOUT BUG ConnRef *connRef10 = new ConnRef(router, 10); srcPt = ConnEnd(shapeRef1, 4); connRef10->setSourceEndpoint(srcPt); dstPt = ConnEnd(junctionRef6); connRef10->setDestEndpoint(dstPt); connRef10->setRoutingType((ConnType)2); #endif // router->deleteConnector(connRef5); router->processTransaction(); ConnRef *mergedConn = junctionRef6->removeJunctionAndMergeConnectors(); router->processTransaction(); router->outputDiagram("output/removeJunctions01"); std::pair<ConnEnd, ConnEnd> ends = mergedConn->endpointConnEnds(); // Expected result: output images should be virtually identical. // Result: An endpoint seems to be disconnected from shapeRef8. bool isConnected = (ends.first.shape() == shapeRef8) || (ends.second.shape() == shapeRef8); delete router; return isConnected ? 0 : 1; };