def points_to_surface(surface, pnts, copy=True, ends=True): """ Project points to a surface. :param surface_like surface: Surface to project points to. :param list pnts: List of point_like entities. Will be converted to :clas:`.Point` instances if not already. :param bool copy: Option to copy the points and project them rather than the original points. :param bool ends: Option to project point to the nearest boundary curve of a surface. :return: List of the projected points. :rtype: list ..note: If a projection fails the point location is not updated. """ if not CheckGeom.is_surface_like(surface): return [] # Make sure a list of Point instances is provided. pnts = CheckGeom.to_points(pnts) # Copy points if desired. if copy: pnts = [p.copy() for p in pnts] # Project each point to the surface and update its location. for p in pnts: ProjectGeom.point(p, surface, ends, update=True) return pnts
def point_on_geom(point, geom, tol=None): """ Check to see if the point is on the geometry. :param point: :param geom: :param tol: :return: *True* if ont geometry, *False* if not and parameter(s). :rtype: tuple """ point = CheckGeom.to_point(point) if CheckGeom.is_curve_like(geom): u = ProjectGeom.invert(point, geom, False) if u is None: return False, None p = geom.eval(u, domain='global') is_on = p.is_equal(point, tol) return is_on, u elif CheckGeom.is_surface_like(geom): u, v = ProjectGeom.invert(point, geom, False) if None in [u, v]: return False, None, None p = geom.eval(u, v, domain='global') is_on = p.is_equal(point, tol) return is_on, u, v return False, None
def surface_by_curve_drag(curve, vector, vmax=1., vmin=-1.): """ Create a surface by dragging a curve along a vector in both direction. :param curve: Curve to drag. :type curve: :class`.BezierCurve`, :class`.NurbsCurve`, or :class`.ICurve` :param array_like vector: Drag direction vector. :param float vmax: Distance to drag in positive v-direction. :param float vmin: Distance to drag in negative v-direction. :return: Surface created from dragging curves. :rtype: :class:`.NurbsSurface` """ tol = Settings.gtol if not CheckGeom.is_curve(curve): return None if CheckGeom.is_icurve(curve): curve = curve.crv3d if vmax < 0.: vmax = 0. if vmin > 0.: vmin = 0. if abs(vmax) <= tol and abs(vmin) <= tol: return None c0 = translate_curve(curve, vector, vmin, False) c1 = translate_curve(curve, vector, vmax, False) return CreateGeom.interpolate_curves([c0, c1])
def create_system_by_points(origin, x_axis, xz_plane): """ Coordinate system by three points. """ origin, x_axis, xz_plane = CheckGeom.to_points([origin, x_axis, xz_plane]) for p in [origin, x_axis, xz_plane]: if not CheckGeom.is_point(p): return None vx = vector_by_points(x_axis, origin) vy = vector_by_points(origin, x_axis, xz_plane) vz = vx.cross(vy) return System(origin, vx, vy, vz)
def line_by_vector(p0, v): """ Create a line by an origin and direction vector. :param p0: :param v: :return: """ p0 = CheckGeom.to_point(p0) if not CheckGeom.is_vector(v): v = array(v, dtype=float64) v = Vector(v, p0) return Line(p0, v)
def _perform(self, point, curve, ends, all_pnts): """ Perform the point to curve projection. """ if CheckGeom.is_icurve(curve): raise NotImplementedError('No Python implementation.') # nsub, npts, results = project_point_to_icurve(point, curve, ends, # all_pnts) elif CheckGeom.is_line(curve): nsub, npts, results = project_point_to_line(point, curve) else: raise NotImplementedError('No Python implementation.') # nsub, npts, results = project_point_to_curve(point, curve, ends, # all_pnts) self._set_results(nsub, npts, results)
def _perform(self, curve, tol): """ Perform curve tessellation. """ if CheckGeom.is_icurve(curve): curve = curve.crv3d if CheckGeom.is_line(curve): verts = array([ curve.eval(0., rtype='ndarray'), curve.eval(curve.length, rtype='ndarray') ], dtype=float64) params = array([0., curve.length], dtype=float64) else: verts, params = adaptive_curve_tessellate(curve, tol) self._verts = verts self._params = params
def add_items(cls, *items): """ Add item to the viewer. :param items: Item(s) to add. """ for item in items: if CheckGeom.is_geom(item): cls.add_geom(item)
def curve_eval2d(curve, u, sref=None, rtype='Point', domain='local', tol=None): """ Evaluate a curve in the parametric space of the surface. :param curve_like curve: Curve to evaluate. :param float u: Curve parameter. :param surface_like sref: The surface to return the 2-D parameters on. :param str rtype: Option to return a NumPy array or Point2D 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 (ICurve only). :return: Parameters on surface at curve parameter. :rtype: tuple """ if not CheckGeom.is_curve_like(curve) or not \ CheckGeom.is_surface_like(sref): return None if tol is None: tol = Settings.gtol / 100. # ICurve already has built-in method. if CheckGeom.is_icurve(curve) and curve.has_surf(sref): return curve.eval2d(u, rtype, domain, tol, sref) # Evaluate curve and invert on surface. p3d = curve.eval(u, domain=domain) u, v = ProjectGeom.invert(p3d, sref, True) if None in [u, v]: return None # Return desired type. if is_array_type(rtype): return array([u, v], dtype=float64) return CreateGeom.point2d((u, v))
def icurve_by_points(surface, p0, p1, isurf=None, trim=True): """ Create an intersection curve between two points on the surface. :param surface: :type surface: :class:`.BezierSurface` or :class`.NurbsSurface` :param point_like p0: Starting point. :param point_like p1: Ending point. :param surface_like isurf: Intersection surface. If *None* if provided then a plane will be created between the two points using the surface normal at *p0*. :param bool trim: Option to trim the curve or not. :return: Intersection curve between *p0* and *p1*. Returns *None* if method fails. :rtype: :class:`.ICurve` """ if not CheckGeom.is_surface(surface): return None if not CheckGeom.is_point_like(p0) or not CheckGeom.is_point_like(p1): return None return create_icurve_by_points(surface, p0, p1, isurf, trim)
def curve_adaptive(curve, tol=None): """ Tessellate a curve using adaptive subdivision. :param curve: Curve to tessellate. :type curve: :class:`.BezierCurve` or :class:`.NurbsCurve` :param float tol: Tolerance to use for flatness criteria. :return: Adaptive curve tessellation. :rtype: :class:`.CurveTessAdaptive` """ if CheckGeom.is_curve_like(curve): return CurveTessAdaptive(curve, tol) return None
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
def surface_adaptive(surface, tol=0.01): """ Tessellate a surface using adaptive subdivision. :param surface: Surface to tessellate. :type surface: :class:`.BezierSurface` or :class:`.NurbsSurface` :param float tol: Tolerance to use for flatness criteria. :return: Adaptive surface tessellation. :rtype: :class:`.SurfaceTessAdaptive` """ if CheckGeom.is_surface(surface): return SurfaceTessAdaptive(surface, tol) return None
def point2d(uv=(0., 0.)): """ Create a 2-D point. :param array_like uv: Location of point. :return: Point at *uv*. :rtype: :class:`.Point2D` """ if CheckGeom.is_point2d(uv): return uv.copy() if len(uv) == 2: return Point2D(uv) return None
def point(pnt, geom, ends=True, all_pnts=False, update=False): """ Project a point to a curve or surface. :param pnt: Point to project. :type pnt: :class:`.Point` :param geom: Curve or surface entity to project point to. :param bool ends: Option to project point to the nearest end point of a curve, or to the nearest boundary curve of a surface if no orthogonal projection is found. :param bool all_pnts: Option to return only the nearest point during the subdivision process (*False*), or all points (*True*). :param bool update: Option to update the location of the *point* rather than returning a projection object. If *True*, then the nearest point will be used to update the point location and a boolean will be returned indicating a successful *True* or unsuccessful *False* projection. :return: Projection object depending on *geom* type. """ pnt = CheckGeom.to_point(pnt) # Project point to curve. if CheckGeom.is_curve_like(geom): proj = ProjectPointToCurve(pnt, geom, ends, all_pnts) return ProjectGeom._update(pnt, proj, update) # Project point to surface. if CheckGeom.is_surface(geom): proj = ProjectPointToSurface(pnt, geom, ends, all_pnts) return ProjectGeom._update(pnt, proj, update) # Project point to plane. if CheckGeom.is_plane(geom): proj = ProjectPointToPlane(pnt, geom) return ProjectGeom._update(pnt, proj, update) return False
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')
def surface_from_plane(plane, w=1., h=1.): """ Create a surface from a plane by specifying surface height and width. :param plane: :param w: :param h: :return: """ if not CheckGeom.is_plane(plane): return None if w <= 0. or h <= 0.: return None w2 = w / 2. h2 = h / 2. p0 = plane.eval(-w2, 0.) p1 = plane.eval(w2, 0.) c = CreateGeom.interpolate_points([p0, p1], p=1) return CreateGeom.surface_by_curve_drag(c, plane.vv.ijk, h2, -h2)
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)
def points_at_kinks(curve, angle=30., u0=0., u1=1., domain='local'): """ Create points at kinks of a curve. :param curve: :param angle: :param u0: :param u1: :param domain: :return: """ if not isinstance(angle, (int, float)): return None if CheckGeom.is_line(curve): results = [(u0, curve.eval(u0)), (u1, curve.eval(u1))] else: results = points_at_kinks(curve, angle, u0, u1, domain) params = [row[0] for row in results] pnts = [row[1] for row in results] return CreatedPoints(pnts, params)
def invert(point, geom, ends=True): """ Return the parameters of the nearest orthogonal projection to the geometry. :param point: Point to project. :type point: :class:`.Point` :param geom: Curve or surface entity to find parameters. :param bool ends: Option to project point to the nearest end point of a curve, or to the nearest boundary curve of a surface if no orthogonal projection is found. :return: Parameter(s) on the geometry of the nearest orthogonal projection. For a curve a single float *u* is returned, for a surface a tuple (u, v) is returned. :rtype: float or tuple .. note:: *None* is returned if no points are found or the method fails. A tuple (*None*, *None*) is returned for a surface. """ point = CheckGeom.to_point(point) if not CheckGeom.is_point(point): if CheckGeom.is_curve_like(geom): return None return None, None if CheckGeom.is_curve_like(geom): proj = ProjectPointToCurve(point, geom, ends) if not proj.success: return None return proj.nearest_param if CheckGeom.is_surface(geom): proj = ProjectPointToSurface(point, geom, ends) if not proj.success: return None, None return proj.nearest_param if CheckGeom.is_plane(geom): proj = ProjectPointToPlane(point, geom) if not proj.success: return None, None return proj.nearest_param return None
def __init__(self, curve, tol=None): super(CurveTessAdaptive, self).__init__('curve_tessellation') self._verts = zeros((0, 3), dtype=float64) self._params = zeros(0, dtype=float64) if CheckGeom.is_curve_like(curve): self._perform(curve, tol)
def __init__(self, point, surface, ends=True, all_pnts=False): super(ProjectPointToSurface, self).__init__() point = CheckGeom.to_point(point) if CheckGeom.is_point(point) and CheckGeom.is_surface(surface): self._perform(point, surface, ends, all_pnts)
def __init__(self, surface, tol=0.01): super(SurfaceTessAdaptive, self).__init__('surface_tessellation') self._verts = zeros((0, 3), dtype=float64) self._triangles = zeros((0, 3), dtype=int32) if CheckGeom.is_surface(surface): self._perform(surface, tol)
def __init__(self, point, curve, ends=True, all_pnts=False): super(ProjectPointToCurve, self).__init__() point = CheckGeom.to_point(point) if CheckGeom.is_point(point) and CheckGeom.is_curve_like(curve): self._perform(point, curve, ends, all_pnts)
def __init__(self, point, plane): super(ProjectPointToPlane, self).__init__() point = CheckGeom.to_point(point) if CheckGeom.is_point(point) and CheckGeom.is_plane(plane): self._perform(point, plane)