def extract_curve(self, u1, v1, u2, v2, basis_shape=None): """ Extract a trimmed curve within the reference surface between the parameters. :param float u1: First u-parameter. :param float v1: First v-parameter. :param float u2: Second u-parameter. :param float v2: Second v-parameter. :param basis_shape: The shape that will be used to intersect with the reference shape. If not provided a plane will be created using the *extract_plane()* method. The parameters should create points that are on or very near the intersection between these two shapes. If they are not they will be projected to the intersection which could yield unanticipated results. :type basis_shape: afem.geometry.entities.Surface or afem.topology.entities.Shape :return: The curve. :rtype: afem.geometry.entities.TrimmedCurve :raise RuntimeError: If method fails. """ p1 = self.sref.eval(u1, v1) p2 = self.sref.eval(u2, v2) if basis_shape is None: basis_shape = self.extract_plane(u1, v1, u2, v2) basis_shape = Shape.to_shape(basis_shape) bop = IntersectShapes(basis_shape, self.sref_shape, approximate=True) shape = bop.shape edges = shape.edges builder = WiresByConnectedEdges(edges) if builder.nwires == 0: msg = 'Failed to extract any curves.' raise RuntimeError(msg) if builder.nwires == 1: wire = builder.wires[0] else: dist = DistancePointToShapes(p1, builder.wires) wire = dist.nearest_shape crv = wire.curve proj = ProjectPointToCurve(p1, crv) if not proj.success: msg = 'Failed to project point to reference curve.' raise RuntimeError(msg) u1c = proj.nearest_param proj = ProjectPointToCurve(p2, crv) if not proj.success: msg = 'Failed to project point to reference curve.' raise RuntimeError(msg) u2c = proj.nearest_param if u1c > u2c: crv.reverse() u1c, u2c = crv.reversed_u(u1c), crv.reversed_u(u2c) return TrimmedCurve.by_parameters(crv, u1c, u2c)