From 2a4477e027998b867d7fcd6e70c543b5999111f9 Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Feb 17 2020 08:42:34 +0000 Subject: perspective: generator sandbox --- diff --git a/c++/perspective/src/SConstruct b/c++/perspective/src/SConstruct index 22c9433..52d964b 100644 --- a/c++/perspective/src/SConstruct +++ b/c++/perspective/src/SConstruct @@ -18,6 +18,7 @@ target = 'perspective' sources = [ 'generator.cpp', + 'generatorsandboxview.cpp', 'main.cpp', 'mainwindow.cpp', 'matrix.cpp', diff --git a/c++/perspective/src/generatorsandboxview.cpp b/c++/perspective/src/generatorsandboxview.cpp new file mode 100644 index 0000000..7c18525 --- /dev/null +++ b/c++/perspective/src/generatorsandboxview.cpp @@ -0,0 +1,153 @@ + +#include "generatorsandboxview.h" + + +GeneratorSandBoxView::GenPoint::GenPoint(const IntVector2 &coord): + coord(coord) +{ + UInt x = UInt(coord.x); + UInt y = UInt(coord.y); + UInt step_x = coord.x ? (x^(x - 1)) >> 1 : UInt(-1); + UInt step_y = coord.y ? (y^(y - 1)) >> 1 : UInt(-1); + + UInt step_xy = (step_x < step_y ? step_x : step_y) + 1; + diamond = step_x != step_y; + + if (!step_xy || step_xy > one) step_xy = one; + step = Int(step_xy); + + level = -1; + for(int l = 0; l <= max_level; ++l) + if (step == (1 << (max_level - l))) + level = l; + assert(level >= 0); +} + +void +GeneratorSandBoxView::GenPoint::get_parents(Set &out_points) const +{ + if (!level || out_points.count(*this)) return; + + GenPoint points[4]; + if (diamond) { + points[0] = GenPoint(coord.x - step, coord.y); + points[1] = GenPoint(coord.x + step, coord.y); + points[2] = GenPoint(coord.x, coord.y - step); + points[3] = GenPoint(coord.x, coord.y + step); + } else { + points[0] = GenPoint(coord.x - step, coord.y - step); + points[1] = GenPoint(coord.x - step, coord.y + step); + points[2] = GenPoint(coord.x + step, coord.y - step); + points[3] = GenPoint(coord.x + step, coord.y + step); + } + for(int i = 0; i < 4; ++i) { + points[i].get_parents(out_points); + out_points.insert(points[i]); + } +} + +void +GeneratorSandBoxView::GenPoint::draw(const Cairo::RefPtr &context) const { + Real fstep = 1/Real(one); + Real fsize = pow(Real(0.9), Real(level)) * fstep; + + Vector2 fcoord(coord.x*fstep, coord.y*fstep); + + if (!level) { + Real s = fsize/sqrt(M_PI); + context->arc(fcoord.x, fcoord.y, s, 0, 2*M_PI); + } else + if (diamond) { + Real s = fsize*sqrt(0.5); + context->move_to(fcoord.x - s, fcoord.y); + context->line_to(fcoord.x, fcoord.y - s); + context->line_to(fcoord.x + s, fcoord.y); + context->line_to(fcoord.x, fcoord.y + s); + context->close_path(); + } else { + Real s = fsize*0.5; + context->move_to(fcoord.x - s, fcoord.y - s); + context->line_to(fcoord.x - s, fcoord.y + s); + context->line_to(fcoord.x + s, fcoord.y + s); + context->line_to(fcoord.x + s, fcoord.y - s); + context->close_path(); + } + context->fill(); +} + + + +GeneratorSandBoxView::GeneratorSandBoxView(): + p0(new View::Point( Vector2(-0.25, -0.25) )), + p1(new View::Point( Vector2( 0.25, 0.25) )) +{ + transform.scale(200, 200); + points.push_back(p0); + points.push_back(p1); +} + +void +GeneratorSandBoxView::on_draw_view(const Cairo::RefPtr &context) { + context->save(); + + const Real ps = get_pixel_size(); + context->set_line_width(ps); + + Pair2 bounds(p0->position, p1->position); + + // calc view bounds + int w = get_allocated_width(); + int h = get_allocated_height(); + Matrix m = transform_from_pixels(); + Pair2 view_bounds(Vector2(INFINITY, INFINITY), Vector2(-INFINITY, -INFINITY)); + view_bounds.expand((m*Vector4(0, 0, 0, 1)).vec2()); + view_bounds.expand((m*Vector4(w, 0, 0, 1)).vec2()); + view_bounds.expand((m*Vector4(0, h, 0, 1)).vec2()); + view_bounds.expand((m*Vector4(w, h, 0, 1)).vec2()); + + // calc int bounds + Real fstep = 1/Real(GenPoint::one); + IntPair2 bounds_int( + IntVector2( Int(ceil (bounds.p0.x/fstep - real_precision)), + Int(ceil (bounds.p0.y/fstep - real_precision)) ), + IntVector2( Int(floor(bounds.p1.x/fstep + real_precision)), + Int(floor(bounds.p1.y/fstep + real_precision)) )); + IntPair2 view_bounds_int( + IntVector2( Int(floor(view_bounds.p0.x/fstep - 2 + real_precision)), + Int(floor(view_bounds.p0.y/fstep - 2 + real_precision)) ), + IntVector2( Int(ceil (view_bounds.p1.x/fstep + 2 - real_precision)), + Int(ceil (view_bounds.p1.y/fstep + 2 - real_precision)) )); + + // draw background points + context->set_source_rgba(0.5, 0.5, 0.5, 0.75); + for(Int x = view_bounds_int.p0.x; x <= view_bounds_int.p1.x; ++x) + for(Int y = view_bounds_int.p0.y; y <= view_bounds_int.p1.y; ++y) + GenPoint(x, y).draw(context); + + // ganer parent points + GenPoint::Set parents; + for(Int x = bounds_int.p0.x; x <= bounds_int.p1.x; ++x) + for(Int y = bounds_int.p0.y; y <= bounds_int.p1.y; ++y) + GenPoint(x, y).get_parents(parents); + context->set_source_rgba(1, 0, 0, 1); + for(GenPoint::Set::const_iterator i = parents.begin(); i != parents.end(); ++i) + i->draw(context); + + // draw selected points + context->set_source_rgba(0, 0, 1, 0.55); + for(Int x = bounds_int.p0.x; x <= bounds_int.p1.x; ++x) + for(Int y = bounds_int.p0.y; y <= bounds_int.p1.y; ++y) + GenPoint(x, y).draw(context); + + // draw bounds + context->set_source_rgba(0, 0, 1, 0.75); + context->move_to(bounds.p0.x, bounds.p0.y); + context->line_to(bounds.p1.x, bounds.p0.y); + context->line_to(bounds.p1.x, bounds.p1.y); + context->line_to(bounds.p0.x, bounds.p1.y); + context->close_path(); + context->stroke(); + + context->restore(); +} + diff --git a/c++/perspective/src/generatorsandboxview.h b/c++/perspective/src/generatorsandboxview.h new file mode 100644 index 0000000..14e64b5 --- /dev/null +++ b/c++/perspective/src/generatorsandboxview.h @@ -0,0 +1,50 @@ +#ifndef GENERATORSANDBOXVIEW_H +#define GENERATORSANDBOXVIEW_H + +#include + +#include "view.h" + + +class GeneratorSandBoxView: public View { +public: + class GenPoint { + public: + enum { + max_level = 4, + one = (1 << max_level) + }; + + typedef std::set Set; + + private: + IntVector2 coord; + int level; + int step; + bool diamond; + + public: + explicit GenPoint(const IntVector2 &coord = IntVector2()); + inline GenPoint(Int x, Int y): GenPoint(IntVector2(x, y)) { } + + inline bool operator< (const GenPoint &other) const { return coord < other.coord; } + + inline const IntVector2& get_coord() const { return coord; } + inline int get_level() const { return level; } + inline int get_step() const { return step; } + inline int get_diamond() const { return diamond; } + + void get_parents(Set &out_points) const; + + void draw(const Cairo::RefPtr &context) const; + }; + + + View::PointPtr p0, p1; + + GeneratorSandBoxView(); + + void on_draw_view(const Cairo::RefPtr &context); +}; + +#endif diff --git a/c++/perspective/src/log.h b/c++/perspective/src/log.h new file mode 100644 index 0000000..2eb50db --- /dev/null +++ b/c++/perspective/src/log.h @@ -0,0 +1,47 @@ +#ifndef LOG_H +#define LOG_H + + +#include +#include +#include + +#include "vector.h" +#include "matrix.h" +#include "perspective.h" + + +class Log { +public: + static const std::string& tab() + { static std::string t = " "; return t; } + static const std::string tab(int count) { + const std::string &t = tab(); + std::string tt; + for(int i = 0; i < count; ++i) tt += t; + return tt; + } + + template + static std::string to_string(const VectorT &x, int w = 0) { + std::stringstream s; + s << "("; + for(int i = 0; i < VectorT::Count; ++i) + s << (i ? ", " : "") << std::setw(w) << x[i] << std::setw(0); + s << ")"; + return s.str(); + } + + template + static std::string to_string(const PairT &x, int w = 0) + { return to_string(x.p0, w) + "-" + to_string(x.p1, w); } + + static std::string to_string(const Matrix3 &x, int w = 0, const std::string &prefix = std::string()) { + std::stringstream s; + for(int i = 0; i < 3; ++i) + s << prefix << to_string(x[i], w) << std::endl; + return s.str(); + } +}; + +#endif diff --git a/c++/perspective/src/main.cpp b/c++/perspective/src/main.cpp index 6ce8f08..93a5c19 100644 --- a/c++/perspective/src/main.cpp +++ b/c++/perspective/src/main.cpp @@ -4,6 +4,7 @@ #include "mainwindow.h" #include "perspectivesandboxview.h" +#include "generatorsandboxview.h" int main(int argc, char **argv) { @@ -13,11 +14,11 @@ int main(int argc, char **argv) { argc, argv, "org.coolbug.lab.perspective"); std::cout << "create window" << std::endl; - //Gtk::Window window; + //MainWindow window; + Gtk::Window window; //window.add(*Gtk::manage(new PerspectiveSandBoxView())); - //window.add(*Gtk::manage(new PerspectiveSandBoxView())); - //window.show_all(); - MainWindow window; + window.add(*Gtk::manage(new GeneratorSandBoxView())); + window.show_all(); std::cout << "run" << std::endl; int result = application->run(window); diff --git a/c++/perspective/src/perspectivesandboxview.cpp b/c++/perspective/src/perspectivesandboxview.cpp index aee0140..0e16576 100644 --- a/c++/perspective/src/perspectivesandboxview.cpp +++ b/c++/perspective/src/perspectivesandboxview.cpp @@ -4,14 +4,6 @@ #include "perspectivesandboxview.h" -View::PointPtr - persp_p0, - persp_px, - persp_py, - persp_p1, - bounds_p0, - bounds_p1; - PerspectiveSandBoxView::PerspectiveSandBoxView(): persp_p0 (new View::Point( Vector2(-1, -1) )), persp_px (new View::Point( Vector2( 1, -1) )),