Пример #1
0
def vector_by_points(p0, p1, p2=None):
    """
    Create a vector defined by two or three points.

    :param p0: Origin of plane.
    :type p0: :class:`.Point` or array_like
    :param p1: Point defining vector *p1* - *p0*.
    :type p1: :class:`.Point` or array_like
    :param p2: Point defining vector *p2* - *p0*.
    :type p2: :class:`.Point` or array_like

    :return: A vector from *p0* to *p1* if only two points are provided,
        or a vector defined by the cross product of *p10* x *p20* if all three
        points are provided.
    :rtype: :class:`.Vector`
    """
    if not isinstance(p0, Point):
        p0 = Point(p0)
    if not isinstance(p1, Point):
        p1 = Point(p1)
    # Cross product if three points are provided.
    if p2 is not None:
        if not isinstance(p2, Point):
            p2 = Point(p2)
        v10 = p1.xyz - p0.xyz
        v20 = p2.xyz - p0.xyz
        vn = cross(v10, v20)
        return Vector(vn, p0)
    # Straight vector if two points are provided.
    return Vector(p1.xyz - p0.xyz, p0)
Пример #2
0
def plane_by_points(p0, p1, p2):
    """
    Create a plane defined by three points.

    :param p0: Origin of plane.
    :type p0: :class:`.Point` or array_like
    :param p1: Point defining vector *p1* - *p0*.
    :type p1: :class:`.Point` or array_like
    :param p2: Point defining vector *p2* - *p0*.
    :type p2: :class:`.Point` or array_like

    :return: A plane with a normal vector defined by the cross product of
        *p10* x *p20* and an x-axis oriented towards *p1*
    :rtype: :class:`.Plane`
    """
    if not isinstance(p0, Point):
        p0 = Point(p0)
    if not isinstance(p1, Point):
        p1 = Point(p1)
    if not isinstance(p2, Point):
        p2 = Point(p2)
    v10 = p1.xyz - p0.xyz
    v20 = p2.xyz - p0.xyz
    vn = cross(v10, v20)
    vv = cross(vn, v10)
    vu = cross(vv, vn)
    vu = Vector(vu, p0)
    vv = Vector(vv, p0)
    vn = Vector(vn, p0)
    return Plane(p0, vn, vu, vv)
Пример #3
0
def array_to_points1d(arr):
    n = arr.shape
    # Detect if weighted points are provided.
    if n[1] == 4:
        # p = (x/w, y/w, z/w).
        return [Point(arr[i, :-1] / arr[i, -1]) for i in range(n[0])]
    elif n[1] == 3:
        # p = (x,y,z).
        return [Point(arr[i]) for i in range(n[0])]
    return []
Пример #4
0
def array_to_points2d(arr):
    nm = arr.shape
    # Detect if weighted points are provided.
    pnts = []
    for i in range(nm[0]):
        pi = []
        for j in range(nm[1]):
            if nm[2] == 4:
                # p = (x/w, y/w, z/w).
                pi.append(Point(arr[i, j, :-1] / arr[i, j, -1]))
            elif nm[2] == 3:
                # p = (x,y,z).
                pi.append(Point(arr[i, j]))
        pnts.append(pi)
    return pnts
Пример #5
0
    def eval(self, u, v, rtype='Point', domain='local'):
        """
        Evaluate surface at parametric points.

        :param float u: Parametric point in u-direction.
        :param float v: Parametric point in v-direction.
        :param str rtype: Option to return a NumPy array or Point instance
            (rtype = 'ndarray' or 'Point').
        :param str domain: Option to use local (0 <= u, v <= 1) or global
            (a <= u, v <= b) domain ('local', 'l', 'global', 'g').

        :return: Point on surface.
        :rtype: :class:`.Point` or ndarray
        """
        if is_array_like(u) and is_array_like(v):
            return self.eval_params(u, v, rtype, domain)

        if is_local_domain(domain):
            u = self.local_to_global_param('u', u)
            v = self.local_to_global_param('v', v)
        pnt = surface_point(self._n, self._p, self._uk,
                            self._m, self._q, self._vk,
                            self._cpw, u, v)
        if is_array_type(rtype):
            return pnt
        else:
            return Point(pnt)
Пример #6
0
def intersect_plane_plane(plane1, plane2):
    """
    Find the intersection of two planes.

    :param plane1: Plane 1 to intersect.
    :type plane1: :class:`.Plane`
    :param plane2: Plane 2 to intersect.
    :type plane2: :class:`.Plane`

    :return: Intersection line of the two planes. Returns *None* if planes
        are parallel.
    :rtype: :class:`.Line`
    """
    # Global parameters.
    n1 = plane1.vn.ijk
    n2 = plane2.vn.ijk
    p1 = plane1.p0.xyz
    p2 = plane2.p0.xyz

    # Cross product to find line vector.
    v = cross(n1, n2)
    vn = norm(v)
    # Return None if planes are parallel.
    if vn <= Settings.atol:
        return None
    v /= vn

    # Find point along intersection vector using intersection of 3 planes.
    d1 = dot(n1, p1)
    d2 = dot(n2, p2)
    n2v = cross(n2, v)
    p0 = Point((d1 * n2v + d2 * cross(v, n1)) / dot(n1, n2v))
    line = Line(p0, Vector(v, p0))
    return line
Пример #7
0
    def deriv(self, u, v, k, l, rtype='Vector', domain='local'):
        """
        Compute the surface derivative.

        :param float u: Parametric point.
        :param float v: Parametric point.
        :param int k: Derivative to return in u-direction (0 <= k <= d).
        :param int l: Derivative to return in v-direction (0 <= l <= d).
        :param str rtype: Option to return a NumPy array or a Vector instance
            (rtype = 'Vector' or 'ndarray').
        :param str domain: Option to use local (0 <= u, v <= 1) or global
            (a <= u, v <= b) domain ('local', 'l', 'global', 'g').

        :return: Surface derivative.
        :rtype: :class:`.Vector` or ndarray
        """
        if self._cp is None:
            return None
        # Use NURBS rational curve derivative to compute Bezier derivative.
        # Convert to global since using a NURBS method.
        if is_local_domain(domain):
            u = self.local_to_global_param('u', u)
            v = self.local_to_global_param('v', v)
        d = k + l
        der = rat_surface_derivs(self._n, self._p, self._uk, self._m, self._q,
                                 self._vk, self._cpw, u, v, d)
        if is_array_type(rtype):
            return der[k, l]
        else:
            p0 = Point(der[0, 0])
            return Vector(der[k, l], p0)
Пример #8
0
    def eval_params(self, ulist, vlist, rtype='Point', domain='local'):
        """
        Evaluate the surface at multiple parameters.

        :param array_like ulist: Parameters in u-direction.
        :param array_like vlist: Parameters in v-direction.
        :param str rtype: Option to return a NumPy array or Point instance
            (rtype = 'ndarray' or 'Point').
        :param str domain: Option to use local (0 <= u, v <= 1) or global
            (a <= u, v <= b) domain ('local', 'l', 'global', 'g').

        :return: Points on surface.
        :rtype: List :class:`.Point` instances or ndarray
        """
        if not is_array_like(ulist) or not is_array_like(vlist):
            return self.eval(ulist, vlist, rtype, domain)

        if not is_local_domain(domain):
            ulist = [self.global_to_local_param('u', ui) for ui in ulist]
            vlist = [self.global_to_local_param('v', vi) for vi in vlist]
        pnts = bezier_surface_points(self._n, self._m, self._cpw, ulist, vlist)
        if is_array_type(rtype):
            return pnts
        else:
            return [Point(pi) for pi in pnts]
Пример #9
0
    def deriv(self, u, k, d=None, rtype='Vector', domain='local'):
        """
        Compute the *k* -th derivative at point *u*.

        :param float u: Parametric point.
        :param int k: Derivative to return (0 <= k <= d).
        :param int d: Highest derivative to compute. If *d* = *None*, then only
            the *k* th derivative will be computed.
        :param str rtype: Option to return a NumPy array or a Vector instance
            (rtype = 'Vector' or 'ndarray').
        :param str domain: Option to use local (0 <= u <= 1) or global
            (a <= u <= b) domain ('local', 'l', 'global', 'g').

        :return: Curve *k* -th derivative.
        :rtype: :class:`.Vector` or ndarray
        """
        if self._cp is None:
            return None
        if d is None:
            d = k
        if is_local_domain(domain):
            u = self.local_to_global_param(u)
        der = rat_curve_derivs(self._n, self._p, self._uk,
                               self._cpw, u, d)
        if is_array_type(rtype):
            return der[k]
        else:
            p0 = Point(der[0])
            return Vector(der[k], p0)
Пример #10
0
def fit_plane(pnts, tol=None):
    """
    Fit a plane to a scattered set of points.

    :param pnts: Points to fit (at least 3 points are required).
    :type pnts: list of :class:`.Point` instances or array_like
    :param float tol: Tolerance for checking the fit. If *None* is
            provided then the plane will be fit to the points. If a float is
            provided then the plane will not be created if the distance from
            any points is greater than *tol*.

    :return: Plane that best fits data.
    :rtype: :class:`.Plane`
    """
    # Convert points to array.
    pnts = array(pnts, dtype=float64)
    if pnts.shape[0] < 3:
        return None

    # Calculate average to use as the plane origin.
    p0 = mean(pnts, axis=0)

    # Move points to centroid.
    pc = pnts - p0

    # Use SVD.
    u, s, v = svd(pc, False)

    # Check that points are not on a line
    if abs(s[2] - s[1]) <= 1.0e-12:
        return None

    # Find min and max values that define normal vector and major and minor
    # axes of the plane.
    indx = argsort(s)
    vn = v[indx[0]]
    vv = v[indx[1]]
    vu = v[indx[2]]

    # Create plane.
    p0 = Point(p0)
    vu = Vector(vu, p0)
    vv = Vector(vv, p0)
    vn = Vector(vn, p0)
    plane = Plane(p0, vn, vu, vv)

    if tol is None:
        return plane

    # Check distance to each point.
    for pi in pnts:
        if abs(plane.dist2pnt(pi)) > tol:
            return None
    return plane
Пример #11
0
 def _set_results(self, nsub, npts, results):
     """
     Set projection results.
     """
     if npts > 0:
         self._subdivisions = nsub
         self._npts = npts
         # Replace the ndarray with a point instance.
         for i in range(npts):
             results[i][0] = Point(results[i][0])
         self._results = results
         # Sort results by distance.
         self._results.sort(key=lambda lst: lst[2])
Пример #12
0
    def point(xyz=(0., 0., 0.)):
        """
        Create a Point.

        :param array_like xyz: Location of point.

        :return: Point at *xyz*.
        :rtype: :class:`.Point`
        """
        if CheckGeom.is_point(xyz):
            return xyz.copy()
        if len(xyz) == 3:
            return Point(xyz)
        return None
Пример #13
0
def line_by_points(p0, p1):
    """
    Create a line defined by two points.

    :param p0: Origin of plane.
    :type p0: :class:`.Point` or array_like
    :param p1: Point defining vector *p1* - *p0*.
    :type p1: :class:`.Point` or array_like

    :return: A line defined by an oriign at *p0* and a vector *p10*.
    :rtype: :class:`.Line`
    """
    if not isinstance(p0, Point):
        p0 = Point(p0)
    v = vector_by_points(p0, p1)
    return Line(p0, v)
Пример #14
0
    def eval(self, u, rtype='Point', *args, **kwargs):
        """
        Evaluate point on line.

        :param float u: Parameter (-inf < u < inf).
        :param str rtype: Option to return a NumPy array or :class:`.Point`
            instance (rtype = 'ndarray' or 'Point').

        :return: Point on line.
        :rtype: :class:`.Point` or ndarray
        """
        pnt = self._p0.xyz + u * self._v.ijk
        if is_array_type(rtype):
            return pnt
        else:
            return Point(pnt)
Пример #15
0
    def eval(self, u=0., v=0., w=0., rtype='Point', *args, **kwargs):
        """
        Evaluate point on the plane at (u, v).

        :param u:
        :param v:
        :param w:
        :param rtype:

        :return:
        """
        pnt = (self._p0.xyz + u * self._vu.ijk + v * self._vv.ijk +
               w * self._vn.ijk)
        if is_array_type(rtype):
            return pnt
        else:
            return Point(pnt)
Пример #16
0
    def to_point(geom):
        """
        Check to see if the entity is a :class:`.Point` instance and return
        the instance if it is. If the entity is point_like, create a new
        :class:`.Point` instance and return it.

        :param geom: Geometric entity or possible array.

        :return: The Point instance if already a point, or a new Point in
            case it is array_like.
        :rtype: :class:`.Point`
        """
        if isinstance(geom, Point):
            return geom
        elif isinstance(geom, (tuple, list, ndarray)):
            return Point(geom)
        return None
Пример #17
0
def create_icurve_by_points(surface, p0, p1, isurf=None, trim=True):
    """
    Create an intersection curve between the two points on the surface.
    """
    # Get surface parameters.
    uv0 = ProjectGeom.invert(p0, surface)
    uv1 = ProjectGeom.invert(p1, surface)
    if None in uv0 or None in uv1:
        return None

    # Re-evaluate in case points were not on surface.
    p0 = surface.eval(uv0[0], uv0[1], domain='global')
    p1 = surface.eval(uv1[0], uv1[1], domain='global')

    # Generate intersection plane if no surface is given.
    if not CheckGeom.is_surface_like(isurf):
        vn = surface.norm(uv0[0], uv0[1], domain='global')
        p2 = Point(p0.xyz + vn.ijk)
        isurf = plane_by_points(p0, p1, p2)
        # If points are colinear return None for now.
        if isurf is None:
            return None

    # Intersect the surface.
    si = IntersectGeom.perform(surface, isurf)
    if not si.success:
        return None
    indx = si.curve_nearest_point(p0)
    icrv = si.get_icurve(indx)

    # Project points to curve.
    u0 = ProjectGeom.invert(p0, icrv)
    u1 = ProjectGeom.invert(p1, icrv)
    if None in [u0, u1]:
        return None

    # Reverse if necessary.
    if u0 > u1:
        icrv.reverse(True)
        u0, u1 = -u0 + icrv.a + icrv.b, -u1 + icrv.a + icrv.b

    # Trim if desired and return.
    if not trim:
        return icrv
    return icrv.extract(u0, u1, domain='global')
Пример #18
0
    def eval(self, dx, dy, dz, rtype='Point', *args, **kwargs):
        """
        Evaluate a point relative to the system.

        :param dx:
        :param dy:
        :param dz:
        :param rtype:
        :param args:
        :param kwargs:

        :return:
        """
        pnt = (self._origin.xyz + dx * self._vx.ijk + dy * self._vy.ijk +
               dz * self._vz.ijk)
        if is_array_type(rtype):
            return pnt
        else:
            return Point(pnt)
Пример #19
0
def plane_by_axes(p0, axes, sys=None):
    """
    Create a plane defined by an origin and standard axes.

    :param p0: Origin of plane.
    :type p0: :class:`.Point` or array_like
    :param axes: Standard axes, one of 'xy', 'xz', or 'yz'.
    :param sys: Reference system for axes.
    :type sys: :class:`.System`

    :return: Plane oriented by axes.
    :rtype: :class:`.Plane`
    """
    if not isinstance(axes, str):
        return None
    if axes.lower() not in ['xy', 'yx', 'xz', 'zx', 'yz', 'zy']:
        return None

    if not isinstance(p0, Point):
        p0 = Point(p0)

    vx = array([1., 0., 0.], dtype=float64)
    vy = array([0., 1., 0.], dtype=float64)
    vz = array([0., 0., 1.], dtype=float64)
    if CheckGeom.is_system(sys):
        vx = sys.vx.ijk
        vy = sys.vy.ijk
        vz = sys.vz.ijk

    if axes.lower() in ['xy', 'yx']:
        p1 = p0.xyz + vx
        p2 = p0.xyz + vy
        return plane_by_points(p0, p1, p2)
    if axes.lower() in ['xz', 'zx']:
        p1 = p0.xyz + vz
        p2 = p0.xyz + vx
        return plane_by_points(p0, p1, p2)
    if axes.lower() in ['yz', 'zy']:
        p1 = p0.xyz + vy
        p2 = p0.xyz + vz
        return plane_by_points(p0, p1, p2)
Пример #20
0
    def eval(self, u, rtype='Point', domain='local', tol=None):
        """
        Evaluate curve at parametric point.

        :param float u: Parametric point.
        :param str rtype: Option to return a NumPy array or Point instance
            (rtype = 'Point' or 'ndarray').
        :param str domain: Option to use local (0 <= u <= 1) or global
            (a <= u <= b) domain ('local', 'l', 'global', 'g').
        :param float tol: Tolerance for point refinement.

        :return: Point on curve.
        :rtype: :class:`.Point` or ndarray
        """
        if is_local_domain(domain):
            u = self.local_to_global_param(u)
        uv1, uv2 = self.eval2d(u, rtype='ndarray', domain='global', tol=tol)
        p3d = self._s1.eval(uv1[0], uv1[1], rtype='ndarray', domain='global')
        if is_array_type(rtype):
            return p3d
        else:
            return Point(p3d)
Пример #21
0
def plane_by_normal(p0, vn):
    """
    Create a plane by an origin and normal vector.

    :param p0: Origin of plane.
    :type p0: :class:`.Point` or array_like
    :param vn: Normal vector of plane.
    :type vn: :class:`.Vector` or array_like

    :return: Plane with given origin and normal vector.
    :rtype: :class:`.Plane`
    """
    if not isinstance(p0, Point):
        p0 = Point(p0)
    if not isinstance(vn, Vector):
        vn = Vector(vn, p0)

    # Try x-axis.
    vu = cross([1., 0., 0.], vn.vxyz)
    if dot(vu, vu) > 0.:
        vv = Vector(cross(vu, vn.vxyz), p0)
        vu = Vector(vu, p0)
        return Plane(p0, vn, vu, vv)

    # Try y-axis.
    vu = cross([0., 1., 0.], vn.vxyz)
    if dot(vu, vu) > 0.:
        vv = Vector(cross(vu, vn.vxyz), p0)
        vu = Vector(vu, p0)
        return Plane(p0, vn, vu, vv)

    # Try z-axis.
    vu = cross([0., 0., 1.], vn.vxyz)
    if dot(vu, vu) > 0.:
        vv = Vector(cross(vu, vn.vxyz), p0)
        vu = Vector(vu, p0)
        return Plane(p0, vn, vu, vv)
    return None
Пример #22
0
    def eval(self, u, v, rtype='Point', domain='local'):
        """
        Evaluate surface at parametric points.

        :param float u: Parametric point in u-direction.
        :param float v: Parametric point in v-direction.
        :param str rtype: Option to return a NumPy array or Point instance
            (rtype = 'Point' or 'ndarray').
        :param str domain: Option to use local (0 <= u, v <= 1) or global
            (a <= u, v <= b) domain ('local', 'l', 'global', 'g').

        :return: Point on surface.
        :rtype: :class:`.Point` or ndarray
        """
        if not is_local_domain(domain):
            u = self.global_to_local_param('u', u)
            v = self.global_to_local_param('v', v)
        pw = deCasteljau2(self._cpw, self._n, self._m, u, v)
        pnt = pw[:-1] / pw[-1]
        if is_array_type(rtype):
            return pnt
        else:
            return Point(pnt)
Пример #23
0
    def eval_params(self, ulist, rtype='Point', domain='local'):
        """
        Evaluate the curve at multiple parameters.

        :param array_like ulist: Curve parameters.
        :param str rtype: Option to return a NumPy array or list of Point
            instances (rtype = 'Point' or 'ndarray').
        :param str domain: Option to use local (0 <= u <= 1) or global
            (a <= u <= b) domain ('local', 'l', 'global', 'g').

        :return: Points at parameters.
        :rtype: List of :class:`.Point` instances or NumPy array
        """
        if not is_array_like(ulist):
            return self.eval(ulist, rtype, domain)

        if is_local_domain(domain):
            ulist = map(self.global_to_local_param, ulist)
        pnts = curve_points(self._n, self._p, self._uk, self._cpw, ulist)
        if is_array_type(rtype):
            return pnts
        else:
            return [Point(pi) for pi in pnts]
Пример #24
0
    def eval(self, u, rtype='Point', domain='local'):
        """
        Evaluate curve at parametric point.

        :param float u: Parametric point.
        :param str rtype: Option to return a NumPy array or Point instance
            (rtype = 'Point' or 'ndarray').
        :param str domain: Option to use local (0 <= u <= 1) or global
            (a <= u <= b) domain ('local', 'l', 'global', 'g').

        :return: Point on curve.
        :rtype: :class:`.Point` or ndarray
        """
        if is_array_like(u):
            return self.eval_params(u, rtype, domain)

        if is_local_domain(domain):
            u = self.local_to_global_param(u)
        pnt = curve_point(self._n, self._p, self._uk, self._cpw, u)
        if is_array_type(rtype):
            return pnt
        else:
            return Point(pnt)
Пример #25
0
def vector_by_axis(axis, origin):
    """
    Create a vector along the specified axis.

    :param str axis: Axis ('x', 'y', or 'z').
    :param array_like origin: Origin of vector.

    :return: Vector along specified axis.
    :rtype: :class:`.Vector`
    """
    if not isinstance(origin, Point):
        origin = Point(origin)

    if not isinstance(axis, str):
        return None
    if axis.lower() not in ['x', 'y', 'z']:
        return None

    if axis.lower() in ['x']:
        return Vector([1., 0., 0.], origin)
    if axis.lower() in ['y']:
        return Vector([0., 1., 0.], origin)
    if axis.lower() in ['z']:
        return Vector([0., 0., 1.], origin)
Пример #26
0
from pynurbs.geometry.creator import CreateGeom
from pynurbs.geometry.intersector import IntersectSurfaceSurface
from pynurbs.geometry.point import Point
from pynurbs.graphics.viewer import Viewer

gui = Viewer()

p0 = Point((0, 0, 0))
p1 = Point((2, 2, 0))
p2 = Point((4, 3, 0))
p3 = Point((8, -2, 0))
c1 = CreateGeom.interpolate_points([p0, p1, p2, p3])

p0 = Point((0, 0, 10))
p1 = Point((2, 2, 10))
p2 = Point((4, 3, 10))
p3 = Point((8, -2, 10))
c2 = CreateGeom.interpolate_points([p0, p1, p2, p3])

s1 = CreateGeom.interpolate_curves([c1, c2])

p0 = Point((0, 5, 5))
p1 = Point((2, 3, 5))
p2 = Point((4, 2, 5))
p3 = Point((8, 5, 5))
c3 = CreateGeom.interpolate_points([p0, p1, p2, p3])

p0 = Point((0, 5, 8))
p1 = Point((2, 3, 8))
p2 = Point((4, 2, 8))
p3 = Point((8, 5, 8))
Пример #27
0
from pynurbs.geometry.creator import CreateGeom
from pynurbs.geometry.intersector import IntersectCurveCurve
from pynurbs.geometry.point import Point
from pynurbs.graphics.viewer import Viewer

gui = Viewer()

p0 = Point((0, 0, 0))
p1 = Point((2, 2, 0))
p2 = Point((4, 3, 0))
p3 = Point((8, -2, 0))

c1 = CreateGeom.interpolate_points([p0, p1, p2, p3])

gui.add_items(p0, p1, p2, p3, c1)
gui.show()

p0 = Point((5, -5, 0))
p1 = Point((10, 8, 0))

c2 = CreateGeom.interpolate_points([p0, p1])

gui.add_items(p0, p1, c2, c1)
gui.show()

cci = IntersectCurveCurve(c1, c2)

gui.add_items(c1, c2, *cci.points)
gui.show()