18typedef std::complex<AAF>
CAAF;
21 bool operator()(
const Point &a,
const Point &b) {
22 return (a[0] < b[0]) || ((a[0] == b[0]) and (a[1] < b[1]));
28 std::optional<Geom::LineSegment> ls =
42 std::optional<Geom::LineSegment> ls =
46 ch.boundary.push_back((*ls)[0]);
47 ch.boundary.push_back((*ls)[1]);
49 for(
int i = 0; i < 4; i++) {
52 ch.boundary.push_back(p);
60 vector<Geom::Point>
result;
62 for(
int i = 0; i < 4; i++) {
64 double z =
dot(cnr, n);
65 if((z > lu[0]) and (z < lu[1]))
68 for(
int i = 0; i < 2; i++) {
71 std::optional<Geom::LineSegment> ls =
75 result.push_back((*ls)[0]);
76 result.push_back((*ls)[1]);
82 for(
size_t i = 2; i <
result.size(); i++) {
95 for (
unsigned int k = 0; k < pts.size(); ++k)
112 for (
unsigned int k = 0; k < pts.size(); ++k)
114 bnd.extendTo(A*pts[k][0]+B - pts[k][1]);
117 return AAF(x, A, B, bnd.
extent(),
124 ch1.narrowest_diameter(a, b,
c);
126 double A = db[1]/db[0];
128 Point mid = (a+aa)/2;
129 double B = mid[1] - A*mid[0];
130 double dB = (a[1] - A*a[0]) - B;
133 return AAF(x, A, B, dB,
139 const double a = ab.min();
140 const double b = ab.max();
142 const double ea = atan(a);
143 const double eb = atan(b);
145 pts.push_back(
Point(a,ea));
146 pts.push_back(
Point(b,eb));
147 const double alpha = (eb-ea)/(b-a);
148 double xs =
sqrt(1/alpha-1);
149 if((a < xs) and (xs < b))
150 pts.push_back(
Point(xs,atan(xs)));
152 if((a < xs) and (xs < b))
153 pts.push_back(
Point(xs,atan(xs)));
160 const double a = ab.min();
161 const double b = ab.max();
164 type = AAF_TYPE_AFFINE;
170 type = (AAF_TYPE)(AAF_TYPE_AFFINE | AAF_TYPE_NAN);
175 const double ea =
log(a);
176 const double eb =
log(b);
178 pts.push_back(
Point(a,ea));
179 pts.push_back(
Point(b,eb));
180 const double alpha = (eb-ea)/(b-a);
182 double xs = 1/(alpha);
183 if((a < xs) and (xs < b))
191 const double a = ab.min();
192 const double b = ab.max();
194 const double ea = exp(a);
195 const double eb = exp(b);
197 pts.push_back(
Point(a,ea));
198 pts.push_back(
Point(b,eb));
199 const double alpha = (eb-ea)/(b-a);
201 double xs =
log(alpha);
202 if((a < xs) and (xs < b))
203 pts.push_back(
Point(xs,exp(xs)));
211 double lx1 =
log(x + 1.0);
212 return 0.665 * (1 + 0.0195 * lx1) * lx1 + 0.04;
217double lambertW(
double x,
double prec = 1E-12,
int maxiters = 100) {
219 const double e = exp(1);
220 for(
int i = 0; i < maxiters; i++) {
221 double we =
w *
pow(e,
w);
222 double w1e = (
w + 1) *
pow(e,
w);
223 if( prec >
abs((x - we) / w1e))
225 w -= (we - x) / (w1e - (
w+2) * (we-x) / (2*
w+2));
231#include <gsl/gsl_errno.h>
232#include <gsl/gsl_math.h>
233#include <gsl/gsl_min.h>
239double fn1 (
double x,
void * params)
241 param_W *pw = (param_W*)params;
242 return (pw->a*x+pw->b) -
lambertW(x);
245double optimise(
void * params,
double a,
double b) {
248 int iter = 0, max_iter = 100;
255 const gsl_min_fminimizer_type *T = gsl_min_fminimizer_brent;
256 gsl_min_fminimizer *s = gsl_min_fminimizer_alloc (T);
257 if(a+1e-10 >= b)
return m;
259 cout << a <<
" " << b <<
" " << m << endl;
260 cout <<
"fn:" <<
fn1(a, params) <<
" " <<
fn1(b, params) <<
" " <<
fn1(m, params) << endl;
261 cout <<
"fn:" << (pw->a*a+pw->b) <<
" " << (pw->a*b+pw->b) <<
" " << (pw->a*m+pw->b) << endl;
263 gsl_min_fminimizer_set (s, &F, m, a, b);
267 status = gsl_min_fminimizer_iterate (s);
269 m = gsl_min_fminimizer_x_minimum (s);
270 a = gsl_min_fminimizer_x_lower (s);
271 b = gsl_min_fminimizer_x_upper (s);
274 = gsl_min_test_interval (a, b, 0.001, 0.0);
277 while (status == GSL_CONTINUE && iter < max_iter);
279 gsl_min_fminimizer_free (s);
287 const double a = ab.min();
288 const double b = ab.max();
289 const double e = exp(1);
292 type = AAF_TYPE_AFFINE;
298 type = (AAF_TYPE)(AAF_TYPE_AFFINE | AAF_TYPE_NAN);
305 pts.push_back(
Point(a,ea));
306 pts.push_back(
Point(b,eb));
307 const double alpha = (eb-ea)/(b-a);
315 if((a < xs) and (xs < b))
323 const double a = ab.min();
324 const double b = ab.max();
328 type = AAF_TYPE_AFFINE;
334 type = (AAF_TYPE)(AAF_TYPE_AFFINE | AAF_TYPE_NAN);
339 const double ea =
pow(a, p);
340 const double eb =
pow(b, p);
342 pts.push_back(
Point(a,ea));
343 pts.push_back(
Point(b,eb));
344 const double alpha = (eb-ea)/(b-a);
348 double xs =
pow(alpha/p, 1./(p-1));
349 if((a < xs) and (xs < b))
350 pts.push_back(
Point(xs,
pow(xs, p)));
352 if((a < xs) and (xs < b))
353 pts.push_back(
Point(xs,
pow(xs, p)));
405class ConvexTest:
public Toy {
411 toggles.push_back(
Toggle(
"Show trials",
false));
412 handles.push_back(&test_window);
414 handles.push_back(&orig_handle);
418 for(
int i = 0; i < 0; i++) {
425 std::vector<Toggle> toggles;
426 AAF (*eval)(AAF, AAF);
430 cairo_set_line_width(cr, 0.3);
444 AAF f = (*eval)(x, y);
445 double a = f.index_coeff(x.get_index(0))/x.index_coeff(x.get_index(0));
446 double b = f.index_coeff(y.get_index(0))/y.index_coeff(y.get_index(0));
447 AAF d = a*x + b*y - f;
451 if(ivl.extent() < 0.5*
L2(n)) {
461 if(f.strictly_neg()) {
469 if(!f.is_partial() and f.is_indeterminate()) {
471 cairo_set_line_width(cr, 0.3);
472 if(f.is_infinite()) {
473 cairo_set_source_rgb(cr, 1, 0.5, 0.5);
474 }
else if(f.is_nan()) {
475 cairo_set_source_rgb(cr, 1, 1, 0);
477 cairo_set_source_rgb(cr, 1, 0, 0);
490 if(f.strictly_neg() or f.straddles_zero()) {
497 for(
int i = 0; i < 4; i++) {
499 if(
dot(n,p) < ivl.middle()) {
504 if(1 && out && (r.
area() < oldr.
area()*0.25)) {
506 recursive_implicit(r, cr,
w);
508 }
else if(1 && (r[1].extent() < oldr[1].extent()*0.5)) {
514 }
else if(1 && (r[0].extent() < oldr[0].extent()*0.5)) {
537 void key_hit(
unsigned keyval,
unsigned modifiers)
override {
538 if(keyval ==
'w') toggles[0].toggle();
else
539 if(keyval ==
'a') toggles[1].toggle();
else
540 if(keyval ==
'q') toggles[2].toggle();
else
541 if(keyval ==
's') toggles[3].toggle();
548 void draw(
cairo_t *cr, std::ostringstream *notify,
int width,
int height,
bool save, std::ostringstream *timer_stream)
override {
550 cairo_set_line_width (cr, 1);
554 cairo_set_line_width(cr, 0.3);
555 cairo_set_source_rgb(cr, 0.5, 0.5, 1);
562 for(
int &
split : splits)
564 show_splits = toggles[0].on;
567 for(
int split : splits)
568 *notify <<
split <<
" + ";
569 *notify <<
" = " << iters;
572 Rect r(test_window.
pts[0], test_window.
pts[1]);
584 AAF f = (*eval)(x, y);
585 double a = f.index_coeff(x.get_index(0))/x.index_coeff(x.get_index(0));
586 double b = f.index_coeff(y.get_index(0))/y.index_coeff(y.get_index(0));
587 AAF d = a*x + b*y - f;
596 if(f.strictly_neg()) {
604 cairo_set_line_width(cr, 0.3);
605 cairo_set_source_rgb(cr, 0.5, 0.5, 0);
618 gm.narrowest_diameter(a, b,
c);
620 cairo_set_line_width(cr, 2);
640int main(
int argc,
char **argv) {
641 init(argc, argv,
new ConvexTest());
Various geometrical calculations.
void draw_line_in_rect(cairo_t *cr, Rect &r, Point n, double c)
AAF trial_eval(AAF x, AAF y)
AAF atan_sample_based(AAF x)
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)
Convex hull data structures.
Lifts one dimensional objects into 2D.
auto floor(Geom::Rect const &rect)
AAF md_sample_based(AAF x, vector< Point > pts)
AAF log_sample_based(AAF x)
double fn1(double x, void *params)
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)
double optimise(void *params, double a, double b)
AAF atan_sample_based(AAF x)
void fill_line_in_rect(cairo_t *cr, Rect &r, Point n, double c)
double desy_lambert_W(double x)
AAF ls_sample_based(AAF x, vector< Point > pts)
double lambertW(double x, double prec=1E-12, int maxiters=100)
OptRect tighten(Rect &r, Point n, Interval lu)
AAF W_sample_based(AAF x)
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)
Point abs(Point const &b)
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)