diff options
Diffstat (limited to 'gui')
-rw-r--r-- | gui/fpgaviewwidget.cc | 131 | ||||
-rw-r--r-- | gui/fpgaviewwidget.h | 28 | ||||
-rw-r--r-- | gui/lineshader.cc | 2 | ||||
-rw-r--r-- | gui/quadtree.h | 111 |
4 files changed, 135 insertions, 137 deletions
diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc index 7e7b6e4f..ac51467c 100644 --- a/gui/fpgaviewwidget.cc +++ b/gui/fpgaviewwidget.cc @@ -31,11 +31,9 @@ NEXTPNR_NAMESPACE_BEGIN -FPGAViewWidget::FPGAViewWidget(QWidget *parent) : - QOpenGLWidget(parent), ctx_(nullptr), paintTimer_(this), - lineShader_(this), zoom_(10.0f), - rendererArgs_(new FPGAViewWidget::RendererArgs), - rendererData_(new FPGAViewWidget::RendererData) +FPGAViewWidget::FPGAViewWidget(QWidget *parent) + : QOpenGLWidget(parent), ctx_(nullptr), paintTimer_(this), lineShader_(this), zoom_(10.0f), + rendererArgs_(new FPGAViewWidget::RendererArgs), rendererData_(new FPGAViewWidget::RendererData) { colors_.background = QColor("#000000"); colors_.grid = QColor("#333"); @@ -126,52 +124,54 @@ float FPGAViewWidget::PickedElement::distance(Context *ctx, float wx, float wy) // Go over its' GraphicElements, and calculate the distance to them. std::vector<float> distances; - std::transform(graphics.begin(), graphics.end(), std::back_inserter(distances), [&](const GraphicElement &ge) -> float { - switch(ge.type) { - case GraphicElement::TYPE_BOX: - { - // If outside the box, return unit distance to closest border. - float outside_x = -1, outside_y = -1; - if (dx < ge.x1 || dx > ge.x2) { - outside_x = std::min(std::abs(dx - ge.x1), std::abs(dx - ge.x2)); - } - if (dy < ge.y1 || dy > ge.y2) { - outside_y = std::min(std::abs(dy - ge.y1), std::abs(dy - ge.y2)); - } - if (outside_x != -1 && outside_y != -1) - return std::min(outside_x, outside_y); - - // If in box, return 0. - return 0; - } - case GraphicElement::TYPE_LINE: - case GraphicElement::TYPE_ARROW: - { - // Return somewhat primitively calculated distance to segment. - // TODO(q3k): consider coming up with a better algorithm - QVector2D w(wx, wy); - QVector2D a(ge.x1, ge.y1); - QVector2D b(ge.x2, ge.y2); - float dw = a.distanceToPoint(w) + b.distanceToPoint(w); - float dab = a.distanceToPoint(b); - return std::abs(dw-dab) / dab; - } - default: - // Not close to antyhing. - return -1; - } - }); + std::transform(graphics.begin(), graphics.end(), std::back_inserter(distances), + [&](const GraphicElement &ge) -> float { + switch (ge.type) { + case GraphicElement::TYPE_BOX: { + // If outside the box, return unit distance to closest border. + float outside_x = -1, outside_y = -1; + if (dx < ge.x1 || dx > ge.x2) { + outside_x = std::min(std::abs(dx - ge.x1), std::abs(dx - ge.x2)); + } + if (dy < ge.y1 || dy > ge.y2) { + outside_y = std::min(std::abs(dy - ge.y1), std::abs(dy - ge.y2)); + } + if (outside_x != -1 && outside_y != -1) + return std::min(outside_x, outside_y); + + // If in box, return 0. + return 0; + } + case GraphicElement::TYPE_LINE: + case GraphicElement::TYPE_ARROW: { + // Return somewhat primitively calculated distance to segment. + // TODO(q3k): consider coming up with a better algorithm + QVector2D w(wx, wy); + QVector2D a(ge.x1, ge.y1); + QVector2D b(ge.x2, ge.y2); + float dw = a.distanceToPoint(w) + b.distanceToPoint(w); + float dab = a.distanceToPoint(b); + return std::abs(dw - dab) / dab; + } + default: + // Not close to antyhing. + return -1; + } + }); // Find smallest non -1 distance. // Find closest element. return *std::min_element(distances.begin(), distances.end(), [&](float a, float b) { - if (a == -1) return false; - if (b == -1) return true; + if (a == -1) + return false; + if (b == -1) + return true; return a < b; }); } -void FPGAViewWidget::renderGraphicElement(RendererData *data, LineShaderData &out, const GraphicElement &el, float x, float y) +void FPGAViewWidget::renderGraphicElement(RendererData *data, LineShaderData &out, const GraphicElement &el, float x, + float y) { if (el.type == GraphicElement::TYPE_BOX) { auto line = PolyLine(true); @@ -234,15 +234,15 @@ void FPGAViewWidget::populateQuadTree(RendererData *data, const DecalXY &decal, if (el.type == GraphicElement::TYPE_BOX) { // Boxes are bounded by themselves. - data->qt->insert(PickQuadTree::BoundingBox(x+el.x1, y+el.y1, x+el.x2, y+el.y2), element); + data->qt->insert(PickQuadTree::BoundingBox(x + el.x1, y + el.y1, x + el.x2, y + el.y2), element); } if (el.type == GraphicElement::TYPE_LINE || el.type == GraphicElement::TYPE_ARROW) { // Lines are bounded by their AABB slightly enlarged. - float x0 = x+el.x1; - float y0 = y+el.y1; - float x1 = x+el.x2; - float y1 = y+el.y2; + float x0 = x + el.x1; + float y0 = y + el.y1; + float x1 = x + el.x2; + float y1 = y + el.y2; if (x1 < x0) std::swap(x0, x1); if (y1 < y0) @@ -301,7 +301,8 @@ void FPGAViewWidget::paintGL() // Render Arch graphics. lineShader_.draw(rendererData_->gfxByStyle[GraphicElement::STYLE_FRAME], colors_.frame, thick11Px, matrix); lineShader_.draw(rendererData_->gfxByStyle[GraphicElement::STYLE_HIDDEN], colors_.hidden, thick11Px, matrix); - lineShader_.draw(rendererData_->gfxByStyle[GraphicElement::STYLE_INACTIVE], colors_.inactive, thick11Px, matrix); + lineShader_.draw(rendererData_->gfxByStyle[GraphicElement::STYLE_INACTIVE], colors_.inactive, thick11Px, + matrix); lineShader_.draw(rendererData_->gfxByStyle[GraphicElement::STYLE_ACTIVE], colors_.active, thick11Px, matrix); // Draw highlighted items. @@ -313,7 +314,7 @@ void FPGAViewWidget::paintGL() flags = rendererData_->flags; } - + { QMutexLocker locker(&rendererArgsLock_); rendererArgs_->flags.clear(); @@ -410,7 +411,6 @@ void FPGAViewWidget::renderLines(void) flags = rendererArgs_->flags; } - // Render decals if necessary. if (decalsChanged) { auto data = std::unique_ptr<FPGAViewWidget::RendererData>(new FPGAViewWidget::RendererData); @@ -469,7 +469,7 @@ void FPGAViewWidget::renderLines(void) for (int i = 0; i < 8; i++) data->gfxHighlighted[i] = rendererData_->gfxHighlighted[i]; } - + rendererData_ = std::move(data); } } @@ -549,15 +549,16 @@ boost::optional<FPGAViewWidget::PickedElement> FPGAViewWidget::pickElement(float // Calculate distances to all elements picked. using ElemDist = std::pair<const PickedElement *, float>; std::vector<ElemDist> distances; - std::transform(elems.begin(), elems.end(), std::back_inserter(distances), - [&](const PickedElement &e) -> ElemDist { - return std::make_pair(&e, e.distance(ctx_, worldx, worldy)); - }); + std::transform(elems.begin(), elems.end(), std::back_inserter(distances), [&](const PickedElement &e) -> ElemDist { + return std::make_pair(&e, e.distance(ctx_, worldx, worldy)); + }); // Find closest non -1 element. - auto closest = std::min_element(distances.begin(), distances.end(), [&](const ElemDist &a, const ElemDist &b){ - if (a.second == -1) return false; - if (b.second == -1) return true; + auto closest = std::min_element(distances.begin(), distances.end(), [&](const ElemDist &a, const ElemDist &b) { + if (a.second == -1) + return false; + if (b.second == -1) + return true; return a.second < b.second; }); @@ -619,7 +620,6 @@ void FPGAViewWidget::mouseMoveEvent(QMouseEvent *event) update(); } - // Invert the projection matrix to calculate screen/mouse to world/grid // coordinates. QVector4D FPGAViewWidget::mouseToWorldCoordinates(int x, int y) @@ -640,8 +640,8 @@ QVector4D FPGAViewWidget::mouseToWorldCoordinates(int x, int y) // operation properly. QVector3D ray = vec.toVector3DAffine(); ray.normalize(); - ray.setX((ray.x()/-ray.z()) * zoom_); - ray.setY((ray.y()/ray.z()) * zoom_); + ray.setX((ray.x() / -ray.z()) * zoom_); + ray.setY((ray.y() / ray.z()) * zoom_); ray.setZ(1.0); vec = viewMove_.inverted() * QVector4D(ray.x(), ray.y(), ray.z(), 1.0); @@ -677,7 +677,6 @@ void FPGAViewWidget::zoom(int level) zoom_ -= level / 100.0; } else { zoom_ -= level / 10.0; - } if (zoom_ < zoomNear_) @@ -708,12 +707,12 @@ void FPGAViewWidget::zoomOutbound() float h = y1 - y0; viewMove_.setToIdentity(); - viewMove_.translate(-w/2, -h/2); + viewMove_.translate(-w / 2, -h / 2); // Our FOV is π/2, so distance for camera to see a plane of width H is H/2. // We add 1 unit to cover half a unit of extra space around. - float distance_w = w/2 + 1; - float distance_h = h/2 + 1; + float distance_w = w / 2 + 1; + float distance_h = h / 2 + 1; zoom_ = std::max(distance_w, distance_h); update(); } diff --git a/gui/fpgaviewwidget.h b/gui/fpgaviewwidget.h index 067f3b7f..4fefe020 100644 --- a/gui/fpgaviewwidget.h +++ b/gui/fpgaviewwidget.h @@ -20,7 +20,6 @@ #ifndef MAPGLWIDGET_H #define MAPGLWIDGET_H -#include <boost/optional.hpp> #include <QMainWindow> #include <QMutex> #include <QOpenGLBuffer> @@ -32,11 +31,12 @@ #include <QThread> #include <QTimer> #include <QWaitCondition> +#include <boost/optional.hpp> +#include "designwidget.h" +#include "lineshader.h" #include "nextpnr.h" #include "quadtree.h" -#include "lineshader.h" -#include "designwidget.h" NEXTPNR_NAMESPACE_BEGIN @@ -108,7 +108,6 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions QSize minimumSizeHint() const override; QSize sizeHint() const override; - public Q_SLOTS: void newContext(Context *ctx); void onSelectedArchItem(std::vector<DecalXY> decals); @@ -124,14 +123,16 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions void clickedWire(WireId wire); private: - const float zoomNear_ = 0.1f; // do not zoom closer than this + const float zoomNear_ = 0.1f; // do not zoom closer than this const float zoomFar_ = 100.0f; // do not zoom further than this const float zoomLvl1_ = 1.0f; const float zoomLvl2_ = 5.0f; - struct PickedElement { + struct PickedElement + { ElementType type; - union Inner { + union Inner + { BelId bel; WireId wire; PipId pip; @@ -202,17 +203,14 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions { bool zoomOutbound; - PassthroughFlags() : - zoomOutbound(false) {} - PassthroughFlags &operator=(const PassthroughFlags &other) noexcept { + PassthroughFlags() : zoomOutbound(false) {} + PassthroughFlags &operator=(const PassthroughFlags &other) noexcept + { zoomOutbound = other.zoomOutbound; return *this; } - void clear() - { - zoomOutbound = false; - } + void clear() { zoomOutbound = false; } }; struct RendererArgs @@ -253,7 +251,7 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions void renderGraphicElement(RendererData *data, LineShaderData &out, const GraphicElement &el, float x, float y); void renderDecal(RendererData *data, LineShaderData &out, const DecalXY &decal); void renderArchDecal(RendererData *data, const DecalXY &decal); - void populateQuadTree(RendererData *data, const DecalXY &decal, const PickedElement& element); + void populateQuadTree(RendererData *data, const DecalXY &decal, const PickedElement &element); boost::optional<PickedElement> pickElement(float worldx, float worldy); QVector4D mouseToWorldCoordinates(int x, int y); QVector4D mouseToWorldDimensions(float x, float y); diff --git a/gui/lineshader.cc b/gui/lineshader.cc index 94a7a010..eba96020 100644 --- a/gui/lineshader.cc +++ b/gui/lineshader.cc @@ -17,8 +17,8 @@ * */ -#include "log.h" #include "lineshader.h" +#include "log.h" NEXTPNR_NAMESPACE_BEGIN diff --git a/gui/quadtree.h b/gui/quadtree.h index f803f770..be677747 100644 --- a/gui/quadtree.h +++ b/gui/quadtree.h @@ -26,14 +26,16 @@ NEXTPNR_NAMESPACE_BEGIN // A node of a QuadTree. Internal. -template <typename CoordinateT, typename ElementT> -class QuadTreeNode +template <typename CoordinateT, typename ElementT> class QuadTreeNode { public: - class BoundingBox { - friend class QuadTreeNode; + class BoundingBox + { + friend class QuadTreeNode; + private: CoordinateT x0_, x1_, y0_, y1_; + public: // Standard constructor for a given (x0,y0), (x1,y1) bounding box // @@ -41,11 +43,11 @@ class QuadTreeNode // @param y0 y coordinate of top-left corner of box // @param x1 x coordinate of bottom-right corner of box // @param y1 y coordinate of bottom-right corner of box - BoundingBox(CoordinateT x0, CoordinateT y0, CoordinateT x1, CoordinateT y1) : - x0_(x0), x1_(x1), y0_(y0), y1_(y1) {} + BoundingBox(CoordinateT x0, CoordinateT y0, CoordinateT x1, CoordinateT y1) : x0_(x0), x1_(x1), y0_(y0), y1_(y1) + { + } - BoundingBox(const BoundingBox &other) : - x0_(other.x0_), x1_(other.x1_), y0_(other.y0_), y1_(other.y1_) {} + BoundingBox(const BoundingBox &other) : x0_(other.x0_), x1_(other.x1_), y0_(other.y0_), y1_(other.y1_) {} // Whether a bounding box contains a given points. // A point is defined to be in a bounding box when it's not lesser than @@ -74,14 +76,16 @@ class QuadTreeNode private: // A pair of Element and BoundingBox that contains it. - class BoundElement { - friend class QuadTreeNode; + class BoundElement + { + friend class QuadTreeNode; + private: BoundingBox bb_; ElementT elem_; + public: - BoundElement(BoundingBox bb, ElementT elem) : - bb_(bb), elem_(elem) {} + BoundElement(BoundingBox bb, ElementT elem) : bb_(bb), elem_(elem) {} }; // The bounding box that this node describes. @@ -103,7 +107,7 @@ class QuadTreeNode // Depth at which this node is - root is at 0, first level at 1, etc. int depth_; - // Checks whether a given bounding box fits within this node - used for + // Checks whether a given bounding box fits within this node - used for // sanity checking on insertion. // @param b bounding box to check // @returns whether b fits in this node entirely @@ -124,7 +128,8 @@ class QuadTreeNode // Used to describe one of 5 possible places an element can exist: // - the node itself (THIS) // - any of the 4 children nodes. - enum Quadrant { + enum Quadrant + { THIS = -1, NW = 0, NE = 1, @@ -175,23 +180,19 @@ class QuadTreeNode return true; } - public: // Standard constructor for node. // @param b BoundingBox this node covers. // @param depth depth at which this node is in the tree // @max_elems how many elements should this node contain before it splits - QuadTreeNode(BoundingBox b, int depth, size_t max_elems = 4) : - bound_(b), max_elems_(max_elems), depth_(depth) - { - } + QuadTreeNode(BoundingBox b, int depth, size_t max_elems = 4) : bound_(b), max_elems_(max_elems), depth_(depth) {} // Disallow copies. QuadTreeNode(const QuadTreeNode &other) = delete; QuadTreeNode &operator=(const QuadTreeNode &other) = delete; // Allow moves. - QuadTreeNode(QuadTreeNode &&other) : - bound_(other.bound_), max_elems_(other.max_elems_), children_(std::move(other.children_)), - splitx_(other.splitx_), splity_(other.splity_), elems_(std::move(other.elems_)), depth_(other.depth_) + QuadTreeNode(QuadTreeNode &&other) + : bound_(other.bound_), max_elems_(other.max_elems_), children_(std::move(other.children_)), + splitx_(other.splitx_), splity_(other.splity_), elems_(std::move(other.elems_)), depth_(other.depth_) { other.children_ = nullptr; } @@ -221,14 +222,14 @@ class QuadTreeNode // Do we have children? if (children_ != nullptr) { - // Put the element either recursively into a child if it fits - // entirely or keep it for ourselves if not. - auto quad = quadrant(k); - if (quad == THIS) { - elems_.push_back(BoundElement(k, std::move(v))); - } else { - return children_[quad].insert(k, std::move(v)); - } + // Put the element either recursively into a child if it fits + // entirely or keep it for ourselves if not. + auto quad = quadrant(k); + if (quad == THIS) { + elems_.push_back(BoundElement(k, std::move(v))); + } else { + return children_[quad].insert(k, std::move(v)); + } } else { // No children and not about to have any. if (!should_split()) { @@ -242,10 +243,17 @@ class QuadTreeNode children_ = decltype(children_)(new QuadTreeNode<CoordinateT, ElementT>[4] { // Note: not using [NW] = QuadTreeNode because that seems to // crash g++ 7.3.0. - /* NW */ QuadTreeNode<CoordinateT, ElementT>(BoundingBox(bound_.x0_, bound_.y0_, splitx_, splity_), depth_+1, max_elems_), - /* NE */ QuadTreeNode<CoordinateT, ElementT>(BoundingBox(splitx_, bound_.y0_, bound_.x1_, splity_), depth_+1, max_elems_), - /* SW */ QuadTreeNode<CoordinateT, ElementT>(BoundingBox(bound_.x0_, splity_, splitx_, bound_.y1_), depth_+1, max_elems_), - /* SE */ QuadTreeNode<CoordinateT, ElementT>(BoundingBox(splitx_, splity_, bound_.x1_, bound_.y1_), depth_+1, max_elems_), + /* NW */ QuadTreeNode<CoordinateT, ElementT>(BoundingBox(bound_.x0_, bound_.y0_, splitx_, splity_), + depth_ + 1, max_elems_), + /* NE */ + QuadTreeNode<CoordinateT, ElementT>(BoundingBox(splitx_, bound_.y0_, bound_.x1_, splity_), + depth_ + 1, max_elems_), + /* SW */ + QuadTreeNode<CoordinateT, ElementT>(BoundingBox(bound_.x0_, splity_, splitx_, bound_.y1_), + depth_ + 1, max_elems_), + /* SE */ + QuadTreeNode<CoordinateT, ElementT>(BoundingBox(splitx_, splity_, bound_.x1_, bound_.y1_), + depth_ + 1, max_elems_), }); // Move all elements to where they belong. auto it = elems_.begin(); @@ -271,20 +279,23 @@ class QuadTreeNode // Dump a human-readable representation of the tree to stdout. void dump(int level) const { - for (int i = 0; i < level; i++) printf(" "); + for (int i = 0; i < level; i++) + printf(" "); printf("loc: % 3d % 3d % 3d % 3d\n", bound_.x0_, bound_.y0_, bound_.x1_, bound_.y1_); if (elems_.size() != 0) { - for (int i = 0; i < level; i++) printf(" "); + for (int i = 0; i < level; i++) + printf(" "); printf("elems: %zu\n", elems_.size()); } if (children_ != nullptr) { - for (int i = 0; i < level; i++) printf(" "); + for (int i = 0; i < level; i++) + printf(" "); printf("children:\n"); - children_[NW].dump(level+1); - children_[NE].dump(level+1); - children_[SW].dump(level+1); - children_[SE].dump(level+1); + children_[NW].dump(level + 1); + children_[NE].dump(level + 1); + children_[SW].dump(level + 1); + children_[SE].dump(level + 1); } } @@ -331,8 +342,7 @@ class QuadTreeNode // // @param CoodinateT scalar type of the coordinate system - int, float, ... // @param ElementT type of the contained element. Must be movable or copiable. -template <typename CoordinateT, typename ElementT> -class QuadTree +template <typename CoordinateT, typename ElementT> class QuadTree { private: // Root of the tree. @@ -348,10 +358,7 @@ class QuadTree // // @param b Bounding box of the entire tree - all comitted elements must // fit within in. - QuadTree(BoundingBox b) : - root_(b, 0) - { - } + QuadTree(BoundingBox b) : root_(b, 0) {} // Inserts a new value at a given bounding box.e // BoundingBoxes are not deduplicated - if two are pushed with the same @@ -367,17 +374,11 @@ class QuadTree } // Dump a human-readable representation of the tree to stdout. - void dump() const - { - root_.dump(0); - } + void dump() const { root_.dump(0); } // Return count of BoundingBoxes/Elements contained. // @returns count of elements contained. - size_t size() const - { - return root_.size(); - } + size_t size() const { return root_.size(); } // Retrieve elements whose bounding boxes cover the given coordinates. // |