__all__ = ('Profile',)

import numbers

from ..lib2d import Point, Matrix, Axes


class Profile(object):
    def __init__(self, *args):
        self.axes = None
        self.points = points = []
        offset = 0.0
        for arg in args:
            if isinstance(arg, Axes):
                if self.axes is not None:
                    raise TypeError('Duplicate Axes() object '
                                    'given to Profile()')
                self.axes = arg
            elif isinstance(arg, numbers.Number):
                offset += arg
            else:
                points.append(Point(arg))
        self.offset = offset

    def is_valid(self):
        '''Whether the object is well formed.'''
        return (self.axes is not None and len(self.points) >= 2)

    def change_axes(self, axes, zero_offset=False):
        '''Express the profile in a different axes.'''
        mx_self = self.axes.get_matrix().get_inverse()
        mx_new = axes.get_matrix()
        dy = (Point.vy(self.offset) if zero_offset else Point())
        ps = [mx_self.apply(p) + dy for p in self.points]
        ps.sort(key=lambda p: p.x)
        ps = tuple(mx_new.apply(p) for p in ps)
        return (Profile(axes, *ps) if zero_offset
                else Profile(self.offset, axes, *ps))

@@ -776,16 +776,191 @@
  %3E= 2)%0A%0A
+    def check(self):%0A        '''Raise an exception if the object is not valid.'''%0A        if not self.is_valid():%0A            raise ValueError('Profile object is not valid')%0A%0A
     def 
@@ -1034,20 +1034,21 @@
 profile 
-in a
+using
  differe
@@ -1071,87 +1071,18 @@
     
-mx_self = self.axes.get_matrix().get_inverse()%0A        mx_new = axes.get_matrix
+self.check
 ()%0A 
@@ -1145,16 +1145,71 @@
 oint())%0A
+        mx_self = self.axes.get_matrix().get_inverse()%0A
         
@@ -1293,16 +1293,51 @@
 p: p.x)%0A
+        mx_new = axes.get_matrix()%0A
         
@@ -1426,16 +1426,16 @@
 _offset%0A
-
         
@@ -1480,8 +1480,974 @@
 , *ps))%0A
+%0A    def get_function(self):%0A        '''Get a function for the profile.'''%0A        self.check()%0A%0A        mx_self = self.axes.get_matrix().get_inverse()%0A        ps = %5Bmx_self.apply(p) for p in self.points%5D%0A        ps.sort(key=lambda p: p.x)%0A        min_x = ps%5B0%5D.x%0A        max_x = ps%5B-1%5D.x%0A        last = %5Bps%5B0%5D, ps%5B1%5D%5D%0A%0A        def fn(x):%0A            p_lhs, p_rhs = last%0A            if p_lhs.x %3C= x %3C= p_rhs.x:%0A                pass%0A            elif min_x %3C= x %3C= max_x:%0A                lhs = 0%0A                rhs = len(ps) - 1%0A                while lhs + 1 %3C rhs:%0A                    ctr = (lhs + rhs)//2%0A                    if x %3C ps%5Bctr%5D.x:%0A                        rhs = ctr%0A                    else:%0A                        lhs = ctr%0A                p_lhs, p_rhs = last%5B0:2%5D = ps%5Blhs:lhs+2%5D%0A            else:%0A                return 0.0%0A            return (p_lhs.y*(p_rhs.x - x) +%0A                    p_rhs.y*(x - p_lhs.x))/(p_rhs.x - p_lhs.x)%0A%0A        return fn%0A

Implement Profile.get_function()