22typedef std::complex<AAF>
CAAF;
25 bool operator()(
const Point &a,
const Point &b) {
26 return (a[0] < b[0]) || ((a[0] == b[0]) and (a[1] < b[1]));
31 std::optional<Geom::LineSegment> ls =
43 vector<Geom::Point>
result;
45 for(
int i = 0; i < 4; i++) {
47 double z =
dot(cnr, n);
48 if((z > lu[0]) and (z < lu[1]))
51 for(
int i = 0; i < 2; i++) {
54 std::optional<Geom::LineSegment> ls =
58 result.push_back((*ls)[0]);
59 result.push_back((*ls)[1]);
65 for(
size_t i = 2; i <
result.size(); i++) {
78 for (
unsigned int k = 0; k < pts.size(); ++k)
95 for (
unsigned int k = 0; k < pts.size(); ++k)
97 bnd.extendTo(A*pts[k][0]+B - pts[k][1]);
100 return AAF(x, A, B, bnd.
extent(),
107 double dia = ch1.narrowest_diameter(a, b,
c);
109 double A = db[1]/db[0];
111 Point mid = (a+aa)/2;
112 double B = mid[1] - A*mid[0];
113 double dB = (a[1] - A*a[0]) - B;
115 std::cout << A <<
"," << B << std::endl;
116 return AAF(x, A, B, dB,
122 const double a = ab.min();
123 const double b = ab.max();
125 const double ea = atan(a);
126 const double eb = atan(b);
128 pts.push_back(
Point(a,ea));
129 pts.push_back(
Point(b,eb));
130 const double alpha = (eb-ea)/(b-a);
131 double xs =
sqrt(1/alpha-1);
132 if((a < xs) and (xs < b))
133 pts.push_back(
Point(xs,atan(xs)));
135 if((a < xs) and (xs < b))
136 pts.push_back(
Point(xs,atan(xs)));
143 const double a = ab.min();
144 const double b = ab.max();
147 type = AAF_TYPE_AFFINE;
153 type = (AAF_TYPE)(AAF_TYPE_AFFINE | AAF_TYPE_NAN);
158 const double ea =
log(a);
159 const double eb =
log(b);
161 pts.push_back(
Point(a,ea));
162 pts.push_back(
Point(b,eb));
163 const double alpha = (eb-ea)/(b-a);
165 double xs = 1/(alpha);
166 if((a < xs) and (xs < b))
174 const double a = ab.min();
175 const double b = ab.max();
177 const double ea = exp(a);
178 const double eb = exp(b);
180 pts.push_back(
Point(a,ea));
181 pts.push_back(
Point(b,eb));
182 const double alpha = (eb-ea)/(b-a);
184 double xs =
log(alpha);
185 if((a < xs) and (xs < b))
186 pts.push_back(
Point(xs,exp(xs)));
193 const double a = ab.min();
194 const double b = ab.max();
197 type = AAF_TYPE_AFFINE;
203 type = (AAF_TYPE)(AAF_TYPE_AFFINE | AAF_TYPE_NAN);
208 const double ea =
pow(a, p);
209 const double eb =
pow(b, p);
211 pts.push_back(
Point(a,ea));
212 pts.push_back(
Point(b,eb));
213 const double alpha = (eb-ea)/(b-a);
217 double xs =
pow(alpha/p, 1./(p-1));
218 if((a < xs) and (xs < b))
219 pts.push_back(
Point(xs,
pow(xs, p)));
221 if((a < xs) and (xs < b))
222 pts.push_back(
Point(xs,
pow(xs, p)));
237 return x*x -y*y + -6*x +10*y-16;
239 return y*y - x*(x-1)*(x+1);
261 return 4*(2*y-4*x)*(2*y+4*x-16)-16*y*y;
262 return pow((x*x + y*y), 2) - (x*x-y*y);
264 return (x*x + y*y-1)*((x-1)*(x-1)+y*y-1);
287class ConvexTest:
public Toy {
293 toggles.push_back(
Toggle(
"Show trials",
false));
294 handles.push_back(&test_window);
296 handles.push_back(&orig_handle);
300 for(
int i = 0; i < 0; i++) {
307 std::vector<Toggle> toggles;
308 AAF (*eval)(AAF, AAF);
313 cairo_set_line_width(cr, 0.3);
327 AAF f = (*eval)(x, y);
329 double a = f.index_coeff(x.get_index(0))/x.index_coeff(x.get_index(0));
330 double b = f.index_coeff(y.get_index(0))/y.index_coeff(y.get_index(0));
331 AAF d = a*x + b*y - f;
335 if(ivl.extent() < 0.5*
L2(n)) {
339 if(!f.is_partial() and f.is_indeterminate()) {
341 cairo_set_line_width(cr, 0.3);
342 if(f.is_infinite()) {
343 cairo_set_source_rgb(cr, 1, 0.5, 0.5);
344 }
else if(f.is_nan()) {
345 cairo_set_source_rgb(cr, 1, 1, 0);
347 cairo_set_source_rgb(cr, 1, 0, 0);
360 if(f.straddles_zero()) {
367 if(1 && out && (r.
area() < oldr.
area()*0.25)) {
369 recursive_implicit(r, cr,
w);
371 }
else if(1 && (r[1].extent() < oldr[1].extent()*0.5)) {
377 }
else if(1 && (r[0].extent() < oldr[0].extent()*0.5)) {
400 void key_hit(
unsigned keyval,
unsigned modifiers)
override {
401 if(keyval ==
'w') toggles[0].toggle();
else
402 if(keyval ==
'a') toggles[1].toggle();
else
403 if(keyval ==
'q') toggles[2].toggle();
else
404 if(keyval ==
's') toggles[3].toggle();
412 if (dir == GDK_SCROLL_UP) {
414 }
else if (dir == GDK_SCROLL_DOWN) {
419 void draw(
cairo_t *cr, std::ostringstream *notify,
int width,
int height,
bool save, std::ostringstream *timer_stream)
override {
421 cairo_set_line_width (cr, 1);
425 cairo_set_line_width(cr, 0.3);
426 cairo_set_source_rgb(cr, 0.5, 0.5, 1);
435 for(
int &
split : splits)
437 show_splits = toggles[0].on;
440 for(
int split : splits)
441 *notify <<
split <<
" + ";
442 *notify <<
" = " << iters;
445 Rect r(test_window.
pts[0], test_window.
pts[1]);
457 AAF f = (*eval)(x, y);
458 double a = f.index_coeff(x.get_index(0))/x.index_coeff(x.get_index(0));
459 double b = f.index_coeff(y.get_index(0))/y.index_coeff(y.get_index(0));
460 AAF d = a*x + b*y - f;
471 cairo_set_line_width(cr, 0.3);
472 cairo_set_source_rgb(cr, 0.5, 0.5, 0);
483 double dia = gm.narrowest_diameter(a, b,
c);
485 cairo_set_line_width(cr, 2);
505int main(
int argc,
char **argv) {
506 init(argc, argv,
new ConvexTest());
Various geometrical calculations.
AAF md_sample_based(AAF x, vector< Point > pts)
AAF log_sample_based(AAF x)
AAF exp_sample_based(AAF x)
void draw_line_in_rect(cairo_t *cr, Rect &r, Point n, double c)
AAF trial_eval(AAF x, AAF y)
AAF pow_sample_based(AAF x, double p)
AAF atan_sample_based(AAF x)
AAF ls_sample_based(AAF x, vector< Point > pts)
OptRect tighten(Rect &r, Point n, Interval lu)
Convex hull based on the Andrew's monotone chain algorithm.
constexpr C extent() const
C right() const
Return rightmost coordinate of the rectangle (+X is to the right).
C area() const
Compute the rectangle's area.
C top() const
Return top coordinate of the rectangle (+Y is downwards).
CPoint midpoint() const
Get the point in the geometric center of the rectangle.
C left() const
Return leftmost coordinate of the rectangle (+X is to the right).
void expandTo(CPoint const &p)
Enlarge the rectangle to contain the given point.
C height() const
Get the vertical extent of the rectangle.
C width() const
Get the horizontal extent of the rectangle.
C bottom() const
Return bottom coordinate of the rectangle (+Y is downwards).
CPoint corner(unsigned i) const
Return the n-th corner of the rectangle.
Range of real numbers that is never empty.
const Vector & SV_solve()
const Vector & solution() const
Axis-aligned rectangle that can be empty.
Two-dimensional point that doubles as a vector.
Axis aligned, non-empty rectangle.
void push_back(double x, double y)
std::vector< Geom::Point > pts
virtual void mouse_pressed(Geom::Point const &pos, unsigned button, unsigned modifiers)
vector< Handle * > handles
virtual void save(FILE *f)
virtual void key_hit(unsigned keyval, unsigned modifiers)
virtual void draw(cairo_t *cr, std::ostringstream *notify, int w, int h, bool save, std::ostringstream *timing_stream)
virtual void scroll(GdkScrollDirection dir, Geom::Point const &delta)
Convex hull data structures.
Lifts one dimensional objects into 2D.
Various utility functions.
SBasisN< n > sqrt(SBasisN< n > const &a, int k)
std::optional< Geom::LineSegment > rect_line_intersect(Geom::Rect &r, Geom::LineSegment ls)
Determine whether & where an (infinite) line intersects a rectangle.
void split(vector< Point > const &p, double t, vector< Point > &left, vector< Point > &right)
Piecewise< SBasis > log(SBasis const &f, double tol=1e-3, int order=3)
SBasis L2(D2< SBasis > const &a, unsigned k)
T dot(D2< T > const &a, D2< T > const &b)
std::vector< Point > intersect(const xAx &C1, const xAx &C2)
void cairo_rectangle(cairo_t *cr, Geom::Rect const &r)
void cairo_line_to(cairo_t *cr, Geom::Point p1)
void cairo_convex_hull(cairo_t *cr, Geom::ConvexHull const &r)
void cairo_move_to(cairo_t *cr, Geom::Point p1)
void toggle_events(std::vector< Toggle > &ts, Geom::Point const &pos, unsigned button)
void cairo_set_source_rgba(cairo_t *cr, colour c)
void draw_toggles(cairo_t *cr, std::vector< Toggle > &ts)
void init(int argc, char **argv, Toy *t, int width=600, int height=600)