Skip to content

Commit

Permalink
Add biding to Ponca
Browse files Browse the repository at this point in the history
include kdtree (but disabled because too slow, need to understand why)
  • Loading branch information
nmellado committed Dec 6, 2023
1 parent 664a440 commit b9390cd
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 21 deletions.
6 changes: 3 additions & 3 deletions src/drawingPass.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ struct DisplayPoint : public DrawingPass {
inline explicit DisplayPoint(const nanogui::Vector4i &pointColor = {0,0,0,255})
: DrawingPass(), m_pointColor(pointColor) {}
void render(const MyView::PointCollection& points, uint8_t*buffer, int w, int h) override{
for (const auto&p : points){
int i (std::floor(p.x()));
int j (std::floor(p.y()));
for (const auto&p : points.point_data()){
int i (std::floor(p.pos().x()));
int j (std::floor(p.pos().y()));
for (int u = -1; u <= 1; ++u ){
for (int v = -1; v <= 1; ++v ){
//this is suboptimal: we check multiple time, could be done better.
Expand Down
30 changes: 27 additions & 3 deletions src/drawingPasses/distanceField.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
struct DistanceField : public DrawingPass {
inline explicit DistanceField() : DrawingPass() {}
void render(const MyView::PointCollection& points, uint8_t*buffer, int w, int h) override{
if(points.point_data().empty()) return;

double normFactor (std::max(w,h));
for (int j = 0; j < h; ++j ) {
for (int i = 0; i < w; ++i) {
auto *b = buffer + (i + j * w) * 4;
int minDist = normFactor; //distance should necessarily be smaller
for (const auto &p: points) {
int u(std::floor(p.x()));
int v(std::floor(p.y()));
for (const auto &p : points.point_data()) {
int u(std::floor(p.pos().x()));
int v(std::floor(p.pos().y()));
auto dist = int(std::sqrt((i-u)*(i-u) + (j-v)*(j-v)));
minDist = std::min(dist, minDist);
}
Expand All @@ -23,3 +25,25 @@ struct DistanceField : public DrawingPass {
}
}
};
struct DistanceFieldWithKdTree : public DrawingPass {
inline explicit DistanceFieldWithKdTree() : DrawingPass() {}
void render(const MyView::PointCollection& points, uint8_t*buffer, int w, int h) override{
if(points.point_data().empty()) return;

double normFactor (std::max(w,h));
for (int j = 0; j < h; ++j ) {
for (int i = 0; i < w; ++i) {
auto *b = buffer + (i + j * w) * 4;
DataPoint::VectorType query (i, j);
auto res = points.nearest_neighbor( query );
if(res.begin()!=res.end()) {
auto nei = points.point_data()[res.get()].pos();
float dist = (nei-query).norm();
auto col = uint (255. * dist / normFactor);
b[0] = b[1] = b[2] = col;
b[3] = 255;
}
}
}
}
};
1 change: 1 addition & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class ExampleApplication : public Screen {
m_passes.clear();
m_passes.push_back( new FillPass( {0,0,0,255}));
m_passes.push_back( new DistanceField());
// m_passes.push_back( new DistanceFieldWithKdTree()); // too slow
m_passes.push_back( new DisplayPoint({255,0,0,255}));

image_view = new MyView(window);
Expand Down
47 changes: 35 additions & 12 deletions src/myview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,25 @@ MyView::isInsideImage(const Vector2f &lp) const {
return true;
}

//#define USE_KDTREE
int
MyView::findPointId(const Vector2f &lp, float epsilon) const{
int i = 0;
for(const auto&p : m_points)
{
if(norm((lp-p)) <= epsilon)
return i;
++i;
if(! m_points.empty()) {
int i = 0;
#ifndef USE_KDTREE
for(const auto&p : m_points) {
Vector2f query(p.x(), p.y());
if (norm((lp - query)) <= epsilon)
return i;
++i;
}
#else
DataPoint::VectorType query(lp.x(), lp.y());
auto res = m_tree.nearest_neighbor(query);
if (res.begin() != res.end() &&
(query-m_tree.point_data()[res.get()].pos()).norm()<epsilon)
return res.get();
#endif
}
return -1;
}
Expand All @@ -45,8 +56,8 @@ MyView::mouse_button_event(const Vector2i &p, int button, bool down, int modifie
auto pointId = findPointId(lp);
if (pointId < 0) { // create new point
std::cout << "MyView::add new point" << std::endl;
m_points.push_back( lp );
m_updateFunction();
m_points.emplace_back( lp.x(), lp.y(), 0, 1 );
updateCollection();
return true;
} else {
m_movedPoint = pointId;
Expand All @@ -71,18 +82,30 @@ MyView::mouse_drag_event(const nanogui::Vector2i &p, const nanogui::Vector2i &re
case 1: //left click
// if is on a point
std::cout << "Move point by [" << rel << "]" << std::endl;
m_points[m_movedPoint] = lp;
m_updateFunction();
m_points[m_movedPoint].x() = lp.x();
m_points[m_movedPoint].y() = lp.y();
updateCollection();
break;
case 2: //right click
// if is on a point
std::cout << "Change normal by [" << rel << "]" << std::endl;
m_updateFunction();
updateCollection();
break;
default:
break;
}
}
}
return true;
}
}

void
MyView::updateCollection() {
// recompute KdTree
if(m_points.empty())
m_tree.clear();
else
m_tree.build(m_points );

m_updateFunction();
}
27 changes: 24 additions & 3 deletions src/myview.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,31 @@
#include <nanogui/imageview.h>
#include <nanogui/vector.h>

#include <Ponca/SpatialPartitioning>

#include <iostream>
#include <optional>
#include <vector>

class DataPoint
{
public:
enum {Dim = 2};
using Scalar = float;
using VectorType = Eigen::Vector<Scalar,Dim>;
inline const auto& pos() const {return m_pos;}
inline const auto& normal() const {return m_normal;}
/// \fixme Use maps to avoid duplication
explicit inline DataPoint(const nanogui::Vector4f &pn)
: m_pos({pn.x(), pn.y()}), m_normal({pn.z(), pn.w()}) {}
private:
VectorType m_pos, m_normal;
};


class MyView : public nanogui::ImageView {
public:
using PointCollection = std::vector<nanogui::Vector2f>;
using PointCollection = Ponca::KdTree<DataPoint>;

/// Initialize the widget
explicit MyView(Widget *parent);
Expand All @@ -29,13 +46,17 @@ class MyView : public nanogui::ImageView {
bool mouse_drag_event(const nanogui::Vector2i &p, const nanogui::Vector2i &rel, int button, int modifiers) override;

/// Read access to point collection
inline const PointCollection& getPointCollection() const { return m_points; }
inline const PointCollection& getPointCollection() const { return m_tree; }

/// Set Update function, called after each point update
inline void setUpdateFunction(std::function<void()> &&f) { m_updateFunction = f; }

private:
PointCollection m_points;
inline void updateCollection();

using PointContainer = std::vector<nanogui::Vector4f>; // stores x,y,nx,ny
PointContainer m_points;
PointCollection m_tree;
std::function<void()> m_updateFunction {[](){}};
int m_movedPoint{-1};
};

0 comments on commit b9390cd

Please sign in to comment.