| 3419 | | plot_division -- the maximum number of subdivisions to |
|---|
| 3420 | | introduce in adaptive refinement. |
|---|
| 3421 | | max_bend -- parameter that affects adaptive refinement |
|---|
| | 3419 | adaptive_recursion -- how many levels of recursion to go before |
|---|
| | 3420 | giving up when doing adaptive refinement |
|---|
| | 3421 | Setting this to 0 disables adaptive refinement |
|---|
| | 3422 | adaptive_tolerance -- how large a difference should be before the |
|---|
| | 3423 | adaptive refinement code considers it significant. |
|---|
| | 3424 | This depends on the interval you use by default. |
|---|
| 3476 | | might insert other points, however, unless plot_division=0. |
|---|
| 3477 | | sage: p=plot(lambda x: 1, (x,0,3), plot_points=4, randomize=False, plot_division=0) |
|---|
| | 3479 | might insert other points, however, unless adaptive_recursion=0. |
|---|
| | 3480 | sage: p=plot(lambda x: 1, (x,0,3), plot_points=4, randomize=False, adaptive_recursion=0) |
|---|
| 3502 | | sage: plot(sin(1/x), (-1, 1), plot_points=1000) |
|---|
| | 3501 | sage: plot(sin(1/x), (-1, 1)) |
|---|
| | 3502 | |
|---|
| | 3503 | The algorithm used to insert extra points is actually pretty simple. On |
|---|
| | 3504 | the picture drawn by the lines below: |
|---|
| | 3505 | sage: p = plot(x^2, (0, 1)) + line([(0,0), (1,1)], rgbcolor='green') |
|---|
| | 3506 | sage: p += line([(0.5, 0.5), (0.5, 0.5^2)], rgbcolor='purple') |
|---|
| | 3507 | sage: p += point(((0, 0), (0.5, 0.5), (0.5, 0.5^2), (1, 1)), rgbcolor='red', pointsize=20) |
|---|
| | 3508 | sage: p += text('A', (-0.05, 0.1), rgbcolor='red') |
|---|
| | 3509 | sage: p += text('B', (1.01, 1.1), rgbcolor='red') |
|---|
| | 3510 | sage: p += text('C', (0.48, 0.57), rgbcolor='red') |
|---|
| | 3511 | sage: p += text('D', (0.53, 0.18), rgbcolor='red') |
|---|
| | 3512 | sage: p |
|---|
| | 3513 | |
|---|
| | 3514 | You have the function (in blue) its approximation (in green) passing by the |
|---|
| | 3515 | points A and B. The algorithm find the middle point in x of A and B, which |
|---|
| | 3516 | is C. It then computes the distance in y between C and D and adds D |
|---|
| | 3517 | to the curve points if it exceeds some treshold. |
|---|
| | 3518 | |
|---|
| | 3519 | If D was added, it recursivly applies the same algorithm between A and D, |
|---|
| | 3520 | and D and B. It does this up to 10 levels deep by default. |
|---|
| | 3521 | |
|---|
| 3657 | | max_bend = float(options['max_bend']) |
|---|
| 3658 | | del options['max_bend'] |
|---|
| 3659 | | plot_division = int(options['plot_division']) |
|---|
| 3660 | | del options['plot_division'] |
|---|
| | 3675 | if 'adaptive_tolerance' in options: |
|---|
| | 3676 | adaptive_tolerance = float(options['adaptive_tolerance']) |
|---|
| | 3677 | del options['adaptive_tolerance'] |
|---|
| | 3678 | else: |
|---|
| | 3679 | adaptive_tolerance = delta * 0.01 |
|---|
| | 3680 | adaptive_recursion = int(options['adaptive_recursion']) |
|---|
| | 3681 | del options['adaptive_recursion'] |
|---|
| | 3682 | |
|---|
| | 3683 | def refine(f, p1, p2, level=0): |
|---|
| | 3684 | if level >= adaptive_recursion: |
|---|
| | 3685 | return [] |
|---|
| | 3686 | x = float((p1[0] + p2[0])/2) |
|---|
| | 3687 | try: |
|---|
| | 3688 | y = float(f(x)) |
|---|
| | 3689 | except (ZeroDivisionError, TypeError, ValueError), msg: |
|---|
| | 3690 | sage.misc.misc.verbose("%s\nUnable to compute f(%s)"%(msg, x), 1) |
|---|
| | 3691 | # give up for this branch |
|---|
| | 3692 | return [] |
|---|
| | 3693 | # this distance calculation is not perfect. |
|---|
| | 3694 | if abs((p1[1] + p2[1])/2 - y) > adaptive_tolerance: |
|---|
| | 3695 | return refine(f, p1, (x, y), level+1) + [(x, y)] +\ |
|---|
| | 3696 | refine(f, (x, y), p2, level+1) |
|---|
| | 3697 | else: |
|---|
| | 3698 | return [] |
|---|
| | 3699 | |
|---|