Esempio n. 1
0
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data.

        The bounding box is computed to be as minimal as possible.
    
        EXAMPLES:

        An example without an angle::

            sage: p = ellipse((-2, 3), 1, 2)
            sage: d = p.get_minmax_data()
            sage: d['xmin']
            -3.0
            sage: d['xmax']
            -1.0
            sage: d['ymin']
            1.0
            sage: d['ymax']
            5.0

        The same example with a rotation of angle `\pi/2`::

            sage: p = ellipse((-2, 3), 1, 2, pi/2)
            sage: d = p.get_minmax_data()
            sage: d['xmin']
            -4.0
            sage: d['xmax']
            0.0
            sage: d['ymin']
            2.0
            sage: d['ymax']
            4.0
        """
        from sage.plot.plot import minmax_data

        epsilon = 0.000001
        cos_angle = cos(self.angle)

        if abs(cos_angle) > 1-epsilon:
            xmax = self.r1
            ymax = self.r2
        elif abs(cos_angle) < epsilon:
            xmax = self.r2
            ymax = self.r1
        else:
            sin_angle = sin(self.angle)
            tan_angle = sin_angle / cos_angle
            sxmax = ((self.r2*tan_angle)/self.r1)**2
            symax = (self.r2/(self.r1*tan_angle))**2
            xmax = (
                abs(self.r1 * cos_angle / sqrt(sxmax+1.)) +
                abs(self.r2 * sin_angle / sqrt(1./sxmax+1.)))
            ymax = (
                abs(self.r1 * sin_angle / sqrt(symax+1.)) +
                abs(self.r2 * cos_angle / sqrt(1./symax+1.)))
            
        return minmax_data([self.x - xmax, self.x + xmax],
                           [self.y - ymax, self.y + ymax],
                           dict=True)
Esempio n. 2
0
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data.

        EXAMPLES::

            sage: d = polygon([[1,2], [5,6], [5,0]], rgbcolor=(1,0,1))[0].get_minmax_data()
            sage: d['ymin']
            0.0
            sage: d['xmin']
            1.0

        ::

            sage: d = point((3, 3), rgbcolor=hue(0.75))[0].get_minmax_data()
            sage: d['xmin']
            3.0
            sage: d['ymin']
            3.0

        ::

            sage: l = line([(100, 100), (120, 120)])[0]
            sage: d = l.get_minmax_data()
            sage: d['xmin']
            100.0
            sage: d['xmax']
            120.0

        """
        from sage.plot.plot import minmax_data
        return minmax_data(self.xdata, self.ydata, dict=True)
Esempio n. 3
0
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data.
        
        EXAMPLES::

            sage: b = bar_chart([-2.3,5,-6,12])
            sage: d = b.get_minmax_data()
            sage: d['xmin']
            0
            sage: d['xmax']
            4
        """
        return minmax_data([0, len(self.datalist)], self.datalist, dict=True)
Esempio n. 4
0
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data.
                
        EXAMPLES::

            sage: x,y = var('x,y')
            sage: d = plot_vector_field((.01*x,x+y), (x,10,20), (y,10,20))[0].get_minmax_data()
            sage: d['xmin']
            10.0
            sage: d['ymin']
            10.0
        """
        from sage.plot.plot import minmax_data
        return minmax_data(self.xpos_array, self.ypos_array, dict=True)
Esempio n. 5
0
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data.
                
        EXAMPLES::

            sage: x,y = var('x,y')
            sage: d = plot_vector_field((.01*x,x+y), (x,10,20), (y,10,20))[0].get_minmax_data()
            sage: d['xmin']
            10.0
            sage: d['ymin']
            10.0
        """
        from sage.plot.plot import minmax_data
        return minmax_data(self.xpos_array, self.ypos_array, dict=True)
Esempio n. 6
0
File: text.py Progetto: drupel/sage
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data. Notice
        that, for text, the box is just the location itself.

        EXAMPLES::

            sage: T = text("Where am I?",(1,1))
            sage: t=T[0]
            sage: t.get_minmax_data()['ymin']
            1.0
            sage: t.get_minmax_data()['ymax']
            1.0
        """
        from sage.plot.plot import minmax_data
        return minmax_data([self.x], [self.y], dict=True)
Esempio n. 7
0
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data. Notice
        that, for text, the box is just the location itself.

        EXAMPLES::

            sage: T = text("Where am I?",(1,1))
            sage: t=T[0]
            sage: t.get_minmax_data()['ymin']
            1.0
            sage: t.get_minmax_data()['ymax']
            1.0
        """
        from sage.plot.plot import minmax_data
        return minmax_data([self.x], [self.y], dict=True)
Esempio n. 8
0
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data.

        EXAMPLES::

            sage: x,y = var('x,y')
            sage: f(x, y) = x^2 + y^2
            sage: d = density_plot(f, (3, 6), (3, 6))[0].get_minmax_data()
            sage: d['xmin']
            3.0
            sage: d['ymin']
            3.0
        """
        from sage.plot.plot import minmax_data
        return minmax_data(self.xrange, self.yrange, dict=True)
Esempio n. 9
0
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data.
        
        EXAMPLES::

            sage: x,y = var('x,y')
            sage: f(x, y) = x^2 + y^2
            sage: d = density_plot(f, (3, 6), (3, 6))[0].get_minmax_data()
            sage: d['xmin']
            3.0
            sage: d['ymin']
            3.0
        """
        from sage.plot.plot import minmax_data
        return minmax_data(self.xrange, self.yrange, dict=True)
Esempio n. 10
0
    def get_minmax_data(self):
        """
        Get minimum and maximum horizontal and vertical ranges
        for the Histogram object.

        EXAMPLES::

            sage: H = histogram([10,3,5], normed=True); h = H[0]
            sage: h.get_minmax_data()
            {'xmax': 10.0, 'xmin': 3.0, 'ymax': 0.4761904761904765, 'ymin': 0}
            sage: G = histogram([random() for _ in range(500)]); g = G[0]
            sage: g.get_minmax_data() # random output
            {'xmax': 0.99729312925213209, 'xmin': 0.00013024562219410285, 'ymax': 61, 'ymin': 0}
            sage: Y = histogram([random()*10 for _ in range(500)], range=[2,8]); y = Y[0]
            sage: ymm = y.get_minmax_data(); ymm['xmax'], ymm['xmin']
            (8.0, 2.0)
            sage: Z = histogram([[1,3,2,0], [4,4,3,3]]); z = Z[0]
            sage: z.get_minmax_data()
            {'xmax': 4.0, 'xmin': 0, 'ymax': 2, 'ymin': 0}
        """
        import numpy
        options = self.options()
        opt = dict(range=options.pop('range', None),
                   bins=options.pop('bins', None),
                   normed=options.pop('normed', None),
                   weights=options.pop('weights', None))

        #check to see if a list of datasets
        if not hasattr(self.datalist[0], '__contains__'):
            ydata, xdata = numpy.histogram(self.datalist, **opt)
            return minmax_data(xdata, [0] + list(ydata), dict=True)
        else:
            m = {'xmax': 0, 'xmin': 0, 'ymax': 0, 'ymin': 0}
            if not options.pop('stacked', None):
                for d in self.datalist:
                    ydata, xdata = numpy.histogram(d, **opt)
                    m['xmax'] = max([m['xmax']] + list(xdata))
                    m['xmin'] = min([m['xmin']] + list(xdata))
                    m['ymax'] = max([m['ymax']] + list(ydata))
                return m
            else:
                for d in self.datalist:
                    ydata, xdata = numpy.histogram(d, **opt)
                    m['xmax'] = max([m['xmax']] + list(xdata))
                    m['xmin'] = min([m['xmin']] + list(xdata))
                    m['ymax'] = m['ymax'] + max(list(ydata))
                return m
Esempio n. 11
0
    def get_minmax_data(self):
        """
        Get minimum and maximum horizontal and vertical ranges
        for the Histogram object.

        EXAMPLES::

            sage: H = histogram([10,3,5], normed=True); h = H[0]
            sage: h.get_minmax_data()
            {'xmax': 10.0, 'xmin': 3.0, 'ymax': 0.4761904761904765, 'ymin': 0}
            sage: G = histogram([random() for _ in range(500)]); g = G[0]
            sage: g.get_minmax_data() # random output
            {'xmax': 0.99729312925213209, 'xmin': 0.00013024562219410285, 'ymax': 61, 'ymin': 0}
            sage: Y = histogram([random()*10 for _ in range(500)], range=[2,8]); y = Y[0]
            sage: ymm = y.get_minmax_data(); ymm['xmax'], ymm['xmin']
            (8.0, 2.0)
            sage: Z = histogram([[1,3,2,0], [4,4,3,3]]); z = Z[0]
            sage: z.get_minmax_data()
            {'xmax': 4.0, 'xmin': 0, 'ymax': 2, 'ymin': 0}
        """
        import numpy
        options=self.options()
        opt=dict(range = options.pop('range',None),
                 bins = options.pop('bins',None),
                 normed = options.pop('normed',None),
                 weights = options.pop('weights', None))
 
        #check to see if a list of datasets
        if not hasattr(self.datalist[0],'__contains__' ):
            ydata,xdata=numpy.histogram(self.datalist, **opt)
            return minmax_data(xdata,[0]+list(ydata), dict=True)
        else:
            m = { 'xmax': 0, 'xmin':0, 'ymax':0, 'ymin':0}
            if not options.pop('stacked',None):
                for d in self.datalist:
                    ydata, xdata = numpy.histogram(d,**opt)
                    m['xmax'] = max([m['xmax']] + list(xdata))
                    m['xmin'] = min([m['xmin']] + list(xdata))
                    m['ymax'] = max([m['ymax']] + list(ydata))
                return m
            else:
                for d in self.datalist:
                    ydata, xdata = numpy.histogram(d,**opt)
                    m['xmax'] = max([m['xmax']] + list(xdata))
                    m['xmin'] = min([m['xmin']] + list(xdata))
                    m['ymax'] = m['ymax'] + max(list(ydata))
                return m
Esempio n. 12
0
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data.

        EXAMPLES::

            sage: p = circle((3, 3), 1)
            sage: d = p.get_minmax_data()
            sage: d['xmin']
            2.0
            sage: d['ymin']
            2.0
        """
        from sage.plot.plot import minmax_data
        return minmax_data([self.x - self.r, self.x + self.r],
                           [self.y - self.r, self.y + self.r],
                           dict=True)
Esempio n. 13
0
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data.
        
        EXAMPLES::

            sage: p = circle((3, 3), 1)
            sage: d = p.get_minmax_data()
            sage: d['xmin']
            2.0
            sage: d['ymin']
            2.0
        """
        from sage.plot.plot import minmax_data
        return minmax_data([self.x - self.r, self.x + self.r],
                           [self.y - self.r, self.y + self.r],
                           dict=True)
Esempio n. 14
0
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data.

        EXAMPLES::

            sage: m = matrix_plot(matrix([[1,3,5,1],[2,4,5,6],[1,3,5,7]]))[0]
            sage: list(sorted(m.get_minmax_data().items()))
            [('xmax', 3.5), ('xmin', -0.5), ('ymax', 2.5), ('ymin', -0.5)]


        """
        from sage.plot.plot import minmax_data
        limits = minmax_data(self.xrange, self.yrange, dict=True)

        # center the matrix so that, for example, the square representing the
        # (0,0) entry is centered on the origin.
        for k, v in limits.iteritems():
            limits[k] -= 0.5
        return limits
Esempio n. 15
0
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data.

        EXAMPLES::

            sage: D = disk((5,4), 1, (pi/2, pi))
            sage: d = D.get_minmax_data()
            sage: d['xmin']
            4.0
            sage: d['ymin']
            3.0
            sage: d['xmax']
            6.0
            sage: d['ymax']
            5.0

        """
        from sage.plot.plot import minmax_data

        return minmax_data([self.x - self.r, self.x + self.r], [self.y - self.r, self.y + self.r], dict=True)
Esempio n. 16
0
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data.

        EXAMPLES::

            sage: m = matrix_plot(matrix([[1,3,5,1],[2,4,5,6],[1,3,5,7]]))[0]
            sage: list(sorted(m.get_minmax_data().items()))
            [('xmax', 3.5), ('xmin', -0.5), ('ymax', -0.5), ('ymin', 2.5)]

        """
        from sage.plot.plot import minmax_data
        limits= minmax_data(self.xrange, self.yrange, dict=True)
        if self.options()['origin']!='lower':
            # flip y-axis so that the picture looks correct.
            limits['ymin'],limits['ymax']=limits['ymax'],limits['ymin']

        # center the matrix so that, for example, the square representing the
        # (0,0) entry is centered on the origin.
        for k,v in limits.iteritems():
            limits[k]-=0.5
        return limits
Esempio n. 17
0
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data.

        EXAMPLES::

            sage: D = disk((5,4), 1, (pi/2, pi))
            sage: d = D.get_minmax_data()
            sage: d['xmin']
            4.0
            sage: d['ymin']
            3.0
            sage: d['xmax']
            6.0
            sage: d['ymax']
            5.0

        """
        from sage.plot.plot import minmax_data
        return minmax_data([self.x - self.r, self.x + self.r],
                           [self.y - self.r, self.y + self.r],
                           dict=True)
Esempio n. 18
0
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data.

        EXAMPLES::

            sage: m = matrix_plot(matrix([[1,3,5,1],[2,4,5,6],[1,3,5,7]]))[0]
            sage: list(sorted(m.get_minmax_data().items()))
            [('xmax', 3.5), ('xmin', -0.5), ('ymax', -0.5), ('ymin', 2.5)]


        """
        from sage.plot.plot import minmax_data
        limits= minmax_data(self.xrange, self.yrange, dict=True)
        if self.options()['origin']!='lower':
            # flip y-axis so that the picture looks correct.
            limits['ymin'],limits['ymax']=limits['ymax'],limits['ymin']

        # center the matrix so that, for example, the square representing the
        # (0,0) entry is centered on the origin.
        for k, v in iteritems(limits):
            limits[k] -= 0.5
        return limits
Esempio n. 19
0
    def get_minmax_data(self):
        """
        Get minimum and maximum horizontal and vertical ranges
        for the Histogram object.

        EXAMPLES::

            sage: H = histogram([10,3,5], density=True); h = H[0]
            sage: h.get_minmax_data()  # rel tol 1e-15
            {'xmax': 10.0, 'xmin': 3.0, 'ymax': 0.4761904761904765, 'ymin': 0}
            sage: G = histogram([random() for _ in range(500)]); g = G[0]
            sage: g.get_minmax_data() # random output
            {'xmax': 0.99729312925213209, 'xmin': 0.00013024562219410285, 'ymax': 61, 'ymin': 0}
            sage: Y = histogram([random()*10 for _ in range(500)], range=[2,8]); y = Y[0]
            sage: ymm = y.get_minmax_data(); ymm['xmax'], ymm['xmin']
            (8.0, 2.0)
            sage: Z = histogram([[1,3,2,0], [4,4,3,3]]); z = Z[0]
            sage: z.get_minmax_data()
            {'xmax': 4.0, 'xmin': 0, 'ymax': 2, 'ymin': 0}

        TESTS::

            sage: h = histogram([10,3,5], normed=True)[0]
            sage: h.get_minmax_data()  # rel tol 1e-15
            {'xmax': 10.0, 'xmin': 3.0, 'ymax': 0.4761904761904765, 'ymin': 0}
        """
        import numpy

        # Extract these options (if they are not None) and pass them to
        # histogram()
        options = self.options()
        opt = {}
        for key in ('range', 'bins', 'normed', 'density', 'weights'):
            try:
                value = options[key]
            except KeyError:
                pass
            else:
                if value is not None:
                    opt[key] = value

        #check to see if a list of datasets
        if not hasattr(self.datalist[0], '__contains__'):
            ydata, xdata = numpy.histogram(self.datalist, **opt)
            return minmax_data(xdata, [0] + list(ydata), dict=True)
        else:
            m = {'xmax': 0, 'xmin': 0, 'ymax': 0, 'ymin': 0}
            if not options.get('stacked'):
                for d in self.datalist:
                    ydata, xdata = numpy.histogram(d, **opt)
                    m['xmax'] = max([m['xmax']] + list(xdata))
                    m['xmin'] = min([m['xmin']] + list(xdata))
                    m['ymax'] = max([m['ymax']] + list(ydata))
                return m
            else:
                for d in self.datalist:
                    ydata, xdata = numpy.histogram(d, **opt)
                    m['xmax'] = max([m['xmax']] + list(xdata))
                    m['xmin'] = min([m['xmin']] + list(xdata))
                    m['ymax'] = m['ymax'] + max(list(ydata))
                return m
Esempio n. 20
0
    def get_minmax_data(self):
        """
        Get minimum and maximum horizontal and vertical ranges
        for the Histogram object.

        EXAMPLES::

            sage: H = histogram([10,3,5], density=True); h = H[0]
            sage: h.get_minmax_data()  # rel tol 1e-15
            {'xmax': 10.0, 'xmin': 3.0, 'ymax': 0.4761904761904765, 'ymin': 0}
            sage: G = histogram([random() for _ in range(500)]); g = G[0]
            sage: g.get_minmax_data() # random output
            {'xmax': 0.99729312925213209, 'xmin': 0.00013024562219410285, 'ymax': 61, 'ymin': 0}
            sage: Y = histogram([random()*10 for _ in range(500)], range=[2,8]); y = Y[0]
            sage: ymm = y.get_minmax_data(); ymm['xmax'], ymm['xmin']
            (8.0, 2.0)
            sage: Z = histogram([[1,3,2,0], [4,4,3,3]]); z = Z[0]
            sage: z.get_minmax_data()
            {'xmax': 4.0, 'xmin': 0, 'ymax': 2, 'ymin': 0}

        TESTS::
            sage: h = histogram([10,3,5], normed=True)[0]
            doctest:warning...:
            DeprecationWarning: the 'normed' option is deprecated. Use 'density' instead.
            See https://trac.sagemath.org/25260 for details.
            sage: h.get_minmax_data()
            doctest:warning ...:
            VisibleDeprecationWarning: Passing `normed=True` on non-uniform bins has always been broken, and computes neither the probability density function nor the probability mass function. The result is only correct if the bins are uniform, when density=True will produce the same result anyway. The argument will be removed in a future version of numpy.
            {'xmax': 10.0, 'xmin': 3.0, 'ymax': 0.476190476190..., 'ymin': 0}
        """
        import numpy

        # Extract these options (if they are not None) and pass them to
        # histogram()
        options = self.options()
        opt = {}
        for key in ('range', 'bins', 'normed', 'density', 'weights'):
            try:
                value = options[key]
            except KeyError:
                pass
            else:
                if value is not None:
                    opt[key] = value

        #check to see if a list of datasets
        if not hasattr(self.datalist[0], '__contains__'):
            ydata, xdata = numpy.histogram(self.datalist, **opt)
            return minmax_data(xdata, [0] + list(ydata), dict=True)
        else:
            m = {'xmax': 0, 'xmin': 0, 'ymax': 0, 'ymin': 0}
            if not options.get('stacked'):
                for d in self.datalist:
                    ydata, xdata = numpy.histogram(d, **opt)
                    m['xmax'] = max([m['xmax']] + list(xdata))
                    m['xmin'] = min([m['xmin']] + list(xdata))
                    m['ymax'] = max([m['ymax']] + list(ydata))
                return m
            else:
                for d in self.datalist:
                    ydata, xdata = numpy.histogram(d, **opt)
                    m['xmax'] = max([m['xmax']] + list(xdata))
                    m['xmin'] = min([m['xmin']] + list(xdata))
                    m['ymax'] = m['ymax'] + max(list(ydata))
                return m
Esempio n. 21
0
    def get_minmax_data(self):
        """
        Returns a dictionary with the bounding box data.

        The bounding box is computed as minimal as possible.

        EXAMPLES:

        An example without angle::

            sage: p = arc((-2, 3), 1, 2)
            sage: d = p.get_minmax_data()
            sage: d['xmin']
            -3.0
            sage: d['xmax']
            -1.0
            sage: d['ymin']
            1.0
            sage: d['ymax']
            5.0

        The same example with a rotation of angle `\pi/2`::

            sage: p = arc((-2, 3), 1, 2, pi/2)
            sage: d = p.get_minmax_data()
            sage: d['xmin']
            -4.0
            sage: d['xmax']
            0.0
            sage: d['ymin']
            2.0
            sage: d['ymax']
            4.0
        """
        from sage.plot.plot import minmax_data

        twopi = 2*pi

        s1 = self.s1
        s2 = self.s2
        s = s2-s1
        s1 = fmod(s1,twopi)
        if s1 < 0: s1 += twopi
        s2 = fmod(s1 + s,twopi)
        if s2 < 0: s2 += twopi

        r1 = self.r1
        r2 = self.r2

        angle = fmod(self.angle,twopi)
        if angle < 0: angle += twopi

        epsilon = float(0.0000001)

        cos_angle = cos(angle)
        sin_angle = sin(angle)

        if cos_angle > 1-epsilon:
            xmin=-r1; ymin=-r2
            xmax=r1; ymax=r2
            axmin = pi; axmax = 0
            aymin = 3*pi/2; aymax = pi/2

        elif cos_angle < -1+epsilon:
            xmin=-r1; ymin=-r2
            xmax=r1; ymax=r2
            axmin=0; axmax=pi
            aymin=pi/2; aymax=3*pi/2

        elif sin_angle > 1-epsilon:
            xmin=-r2; ymin=-r1
            xmax=r2; ymax=r1
            axmin = pi/2; axmax = 3*pi/2
            aymin = pi; aymax = 0

        elif sin_angle < -1+epsilon:
            xmin=-r2; ymin=-r1
            xmax=r2; ymax=r1
            axmin = 3*pi/2; axmax = pi/2
            aymin = 0; aymax = pi

        else:
            tan_angle = sin_angle / cos_angle
            axmax = atan(-r2/r1*tan_angle)
            if axmax < 0: axmax += twopi
            xmax = (
              r1 * cos_angle * cos(axmax) -
              r2 * sin_angle * sin(axmax))
            if xmax < 0:
                xmax = -xmax
                axmax = fmod(axmax+pi,twopi)
            xmin = -xmax
            axmin = fmod(axmax + pi,twopi)

            aymax = atan(r2/(r1*tan_angle))
            if aymax < 0: aymax += twopi
            ymax = (
              r1 * sin_angle * cos(aymax) +
              r2 * cos_angle * sin(aymax))
            if ymax < 0:
                ymax = -ymax
                aymax = fmod(aymax+pi,twopi)
            ymin = -ymax
            aymin = fmod(aymax + pi, twopi)

        if s < twopi-epsilon: # bb determined by the sector
            def is_cyclic_ordered(x1,x2,x3):
                return (
                  (x1 < x2 and x2 < x3) or
                  (x2 < x3 and x3 < x1) or
                  (x3 < x1 and x1 < x2))

            x1 = cos_angle*r1*cos(s1) - sin_angle*r2*sin(s1)
            x2 = cos_angle*r1*cos(s2) - sin_angle*r2*sin(s2)
            y1 = sin_angle*r1*cos(s1) + cos_angle*r2*sin(s1)
            y2 = sin_angle*r1*cos(s2) + cos_angle*r2*sin(s2)

            if is_cyclic_ordered(s1,s2,axmin): xmin = min(x1,x2)
            if is_cyclic_ordered(s1,s2,aymin): ymin = min(y1,y2)
            if is_cyclic_ordered(s1,s2,axmax): xmax = max(x1,x2)
            if is_cyclic_ordered(s1,s2,aymax): ymax = max(y1,y2)

        return minmax_data([self.x + xmin, self.x + xmax],
                           [self.y + ymin, self.y + ymax],
                           dict=True)
Esempio n. 22
0
    def get_minmax_data(self):
        r"""
        Return a dictionary with the bounding box data.

        The bounding box is computed as minimal as possible.

        EXAMPLES:

        An example without angle::

            sage: p = arc((-2, 3), 1, 2)
            sage: d = p.get_minmax_data()
            sage: d['xmin']
            -3.0
            sage: d['xmax']
            -1.0
            sage: d['ymin']
            1.0
            sage: d['ymax']
            5.0

        The same example with a rotation of angle `\pi/2`::

            sage: p = arc((-2, 3), 1, 2, pi/2)
            sage: d = p.get_minmax_data()
            sage: d['xmin']
            -4.0
            sage: d['xmax']
            0.0
            sage: d['ymin']
            2.0
            sage: d['ymax']
            4.0
        """
        from sage.plot.plot import minmax_data

        twopi = 2 * pi

        s1 = self.s1
        s2 = self.s2
        s = s2 - s1
        s1 = fmod(s1, twopi)
        if s1 < 0:
            s1 += twopi
        s2 = fmod(s1 + s, twopi)
        if s2 < 0:
            s2 += twopi

        r1 = self.r1
        r2 = self.r2

        angle = fmod(self.angle, twopi)
        if angle < 0:
            angle += twopi

        epsilon = float(0.0000001)

        cos_angle = cos(angle)
        sin_angle = sin(angle)

        if cos_angle > 1 - epsilon:
            xmin = -r1
            ymin = -r2
            xmax = r1
            ymax = r2
            axmin = pi
            axmax = 0
            aymin = 3 * pi / 2
            aymax = pi / 2

        elif cos_angle < -1 + epsilon:
            xmin = -r1
            ymin = -r2
            xmax = r1
            ymax = r2
            axmin = 0
            axmax = pi
            aymin = pi / 2
            aymax = 3 * pi / 2

        elif sin_angle > 1 - epsilon:
            xmin = -r2
            ymin = -r1
            xmax = r2
            ymax = r1
            axmin = pi / 2
            axmax = 3 * pi / 2
            aymin = pi
            aymax = 0

        elif sin_angle < -1 + epsilon:
            xmin = -r2
            ymin = -r1
            xmax = r2
            ymax = r1
            axmin = 3 * pi / 2
            axmax = pi / 2
            aymin = 0
            aymax = pi

        else:
            tan_angle = sin_angle / cos_angle
            axmax = atan(-r2 / r1 * tan_angle)
            if axmax < 0:
                axmax += twopi
            xmax = (r1 * cos_angle * cos(axmax) - r2 * sin_angle * sin(axmax))
            if xmax < 0:
                xmax = -xmax
                axmax = fmod(axmax + pi, twopi)
            xmin = -xmax
            axmin = fmod(axmax + pi, twopi)

            aymax = atan(r2 / (r1 * tan_angle))
            if aymax < 0:
                aymax += twopi
            ymax = (r1 * sin_angle * cos(aymax) + r2 * cos_angle * sin(aymax))
            if ymax < 0:
                ymax = -ymax
                aymax = fmod(aymax + pi, twopi)
            ymin = -ymax
            aymin = fmod(aymax + pi, twopi)

        if s < twopi - epsilon:  # bb determined by the sector

            def is_cyclic_ordered(x1, x2, x3):
                return ((x1 < x2 and x2 < x3) or (x2 < x3 and x3 < x1)
                        or (x3 < x1 and x1 < x2))

            x1 = cos_angle * r1 * cos(s1) - sin_angle * r2 * sin(s1)
            x2 = cos_angle * r1 * cos(s2) - sin_angle * r2 * sin(s2)
            y1 = sin_angle * r1 * cos(s1) + cos_angle * r2 * sin(s1)
            y2 = sin_angle * r1 * cos(s2) + cos_angle * r2 * sin(s2)

            if is_cyclic_ordered(s1, s2, axmin):
                xmin = min(x1, x2)
            if is_cyclic_ordered(s1, s2, aymin):
                ymin = min(y1, y2)
            if is_cyclic_ordered(s1, s2, axmax):
                xmax = max(x1, x2)
            if is_cyclic_ordered(s1, s2, aymax):
                ymax = max(y1, y2)

        return minmax_data([self.x + xmin, self.x + xmax],
                           [self.y + ymin, self.y + ymax],
                           dict=True)