def add_triangle_grid(p0, p1, p2, nedge, bnd=0): """Creates structured grid in triangle area :param list-of-floats p0: :param list-of-floats p1: :param list-of-floats p2: triangle vertices in [x, y] format :param int nedge: partition of triangle edges :param int-or-list-of-int bnd: boundary types for outer contour :return: identifier of newly created grid Resulting grid will contain quadrangle cells everywhere except area near ``p0``-``p2`` edge where triangle cells will be built. """ icheck(0, Point2D()) icheck(1, Point2D(noteq=[p0])) icheck(2, Point2D(noteq=[p0, p1])) icheck(3, UInt(minv=1)) icheck(4, ListOr1(ZType(), llen=3)) bnd = bnd[:3] if isinstance(bnd, list) else [bnd, bnd, bnd] c = com.gridcom.AddTriGrid({ "vertices": [p0, p1, p2], "nedge": nedge, "bnd": bnd }) flow.exec_command(c) return c.added_grids2()[0]
def add_rect_contour(p0, p1, bnd=0): """Adds four point closed rectangular contour. :param list-of-floats p0: :param list-of-floats p1: bottom left and top right coordinates of the contour :param bnd: single or list of 4 boundary identifiers (bottom, right, top, left) for contour segments. With the default value no boundary types will be set. :return: Contour identifier """ icheck(0, Point2D()) icheck(1, Point2D(grthan=p0)) icheck(2, ListOr1(ZType(), llen=4)) if isinstance(bnd, list): b = bnd[0:4] else: b = [bnd, bnd, bnd, bnd] c = com.contcom.AddRectCont({"p0": p0, "p1": p1, "bnds": b}) flow.exec_command(c) return c.added_contours2()[0]
def add_unf_hex_grid(area, cell_radius, strict=False): """ Builds grid with regular hexagonal cells :param area: defines meshing area. If given as ``[[x, y], radius]`` then represents hexagonal area; if ``[[x0, y0], [x1, y1]]`` then it is a rectangle defined by bottom-left and top-right points. :param float cell_radius: radius of hexagonal cell. :param bool strict: forces grid stretch to guarantee that all outer rectangle corners lie in the centers of cells. See details in :ref:`hexgrid` """ icheck(0, List(Any())) icheck( 0, CompoundList(Point2D(), Or(Float(grthan=0.0), Point2D(grthan=area[0])), llen=2)) icheck(1, Float(grthan=0.)) icheck(2, Bool()) simpar = [area[0][0], area[0][1]] if isinstance(area[1], list): simpar.append(area[1][0]) simpar.append(area[1][1]) else: simpar.append(area[1]) args = {"area": simpar, "crad": cell_radius, "strict": strict} c = com.gridcom.AddUnfHexGrid(args) flow.exec_command(c) return c.added_grids2()[0]
def add_circ_contour(p0, rad, n_arc, bnd=0): """Adds circle contour from given center and radius. :param list-of-floats p0: circle center in [x, y] format :param float rad: circle radius :param int n_arc: partition of circle arc :param bnd: boundary identifier for contour. :return: Contour identifier """ icheck(0, Point2D()) icheck(1, Float(grthan=0.0)) icheck(2, UInt(minv=3)) icheck(3, ZType()) c = com.contcom.AddCircCont({ "p0": p0, "rad": rad, "na": n_arc, "bnd": bnd }) flow.exec_command(c) return c.added_contours2()[0]
def create_spline_contour(pnts, bnds=0, nedges=100): """ Creates singly connected contour as a parametric cubic spline. :param list-of-list-of-floats pnts: sequence of points. If coordinates of first and last points are equal then resulting contour will be closed. :param single-or-list-of-boundary-identifiers bnds: boundary type for each contour segment bounded by **pnts** or single identifier for the whole contour. :param int nedges: number of line segments of resulting contour. Should be equal or greater than the number of sections defined by **pnts**. :returns: contour identifier """ icheck(0, List(Point2D(), minlen=3)) icheck(1, ListOr1(ZType(), llen=len(pnts) - 1)) icheck(2, UInt(minv=len(pnts) - 1)) b = bnds if isinstance(bnds, list) else [bnds] c = com.contcom.CreateSpline({"points": pnts, "bnds": b, "nedges": nedges}) flow.exec_command(c) return c.added_contours2()[0]
def pebi_fill(domain, constr=[], pts=[]): """Builds perpendicular bisector cells in given domain. :param domain: single or list of closed contours representing bounding domain :param constr: single or list of contours representing meshing constraints :param pts: set of points in ``[len0, [x0, y0], ...]`` format where ``x, y`` are coordinates of internal vertices which should be embedded into the resulting grid, ``len`` - size of adjacent cells :return: grid identifier A contour tree will be built using all closed contours passed as **domain** parameter. Only the interior parts of this tree will be meshed. Contours passed by **domain** should not intersect each other, but could intersect **constr** contours. Routine can produce concave cells (as a result of bad size control or near the concave domain boundary vertices). Use :func:`heal_grid` routine with ``convex_cells`` option to fix this. See details in :ref:`unstructured-meshing`. """ icheck(0, UListOr1(ACont2D())) icheck(1, UListOr1(ACont2D())) icheck(2, CompoundList(Float(grthan=0.0), Point2D())) return _triquad(domain, constr, pts, 'pebi')
def add_circ_contour3(p0, p1, curv, n_arc, bnd=0): """Adds circle contour from given arc points and curvature. :param list-of-floats p0: :param list-of-floats p1: circle arc points in [x, y] format :param float curv: circle curvature. Equals ``1.0/radius``. :param int n_arc: partition of circle arc :param bnd: boundary identifier for contour. With the default value no boundary types will be set. :return: Contour identifier In the resulting circle ``p0``-``p1`` arc with counterclockwise direction will be shorter then ``p1``-``p0`` arc. """ from hybmeshpack.basic.geom import angle_3pnt icheck(0, Point2D()) icheck(1, Point2D(noteq=[p0])) icheck(2, Float(grthan=0.0)) icheck(3, UInt(minv=3)) icheck(4, ZType()) p0, p1, curv = map(float, p0), map(float, p1), float(curv) xa, ya = p1[0] - p0[0], p1[1] - p0[1] r = abs(1.0 / curv) a, b, c = -2.0 * xa, -2.0 * ya, xa * xa + ya * ya s = a * a + b * b x0, y0 = -a * c / s, -b * c / s d = r * r - c * c / s mult = math.sqrt(d / s) cx1 = x0 + b * mult cy1 = y0 - a * mult cx2 = x0 - b * mult cy2 = y0 + a * mult a1 = angle_3pnt((0.0, 0.0), (cx1, cx2), (xa, ya)) if (a1 < math.pi): cx, cy = cx1, cy1 else: cx, cy = cx2, cy2 return add_circ_contour([cx + p0[0], cy + p0[1]], r, n_arc, bnd)
def build_boundary_grid1(cont, partition, direction, pstart=None, pend=None, range_angles=[40, 125, 235, 275]): """Builds a singly-connected boundary grid near given contour. :param cont: source contour (or grid) identifier :param list-of-float partition: partition in perpendicular direction. :param str direction: 'left'/'right' :param pstart: :param pend: points in [x, y] format which define the exact segment of the contour for building grid. If both are None hence whole contour (or all subcontours) will be used. :param range_angles: list of 4 angle values (deg) which define algorithms for contour bends treatment. :returns: identifier of the newly created grid. This is a wrapper for a :func:`build_boundary_grid` with simplified interface. It allows to build a boundary grid with constant partition options using existing contour segmentation for horizontal stepping. """ icheck(0, ACont2D()) icheck(1, IncList(Float(), startfrom=0.0)) icheck(2, OneOf('left', 'right')) icheck(3, NoneOr(Point2D())) icheck(4, NoneOr(Point2D(noteq=pstart))) icheck(5, IncList(Float(within=[0, 360, '[]']))) bo = BoundaryGridOptions(cont, partition, direction, bnd_stepping='no', range_angles=range_angles, start_point=pstart, end_point=pend) return build_boundary_grid([bo])
def reflect_geom(objs, pnt1, pnt2): """ Makes a reflection of 2d geometry objects over a given line :param objs: identifier or list of identifiers of 2d objects to reflect :param list-of-float pnt1: :param list-of-float pnt2: points in [x, y] format which define a line to reflect over :returns: None """ icheck(0, UListOr1(ACont2D())) icheck(1, Point2D()) icheck(2, Point2D(noteq=[pnt1])) ob = objs if isinstance(objs, list) else [objs] c = com.objcom.ReflectGeom({"names": ob, "p1": pnt1, "p2": pnt2}) flow.exec_command(c)
def matched_partition(cont, step, influence, ref_conts=[], ref_pts=[], angle0=30., power=3.): """ Makes a contour partition with respect to other contours partitions and given reference points :param cont: target contour. :param float step: default contour step size. :param float influence: influence radius of size conditions. :param ref_conts: list of contours which segmentation will be treated as target segmentation conditions. :param ref_pts: reference points given as ``[step0, [x0, y0], step1, [x1, y1], ...]`` list. :param float angle0: existing contour vertices which provide turns outside of ``[180 - angle0, 180 + angle0]`` degrees range will be preserved regardless of other options :param positive-float power: shows power of weight calculation function. As this parameter increases size transitions along contour become less smooth and more sensible to size conditions. See :ref:`matchedcontmeshing` for details. """ icheck(0, ACont2D()) icheck(1, Float(grthan=0.0)) icheck(2, Float(grthan=0.0)) icheck(3, UList(ACont2D())) icheck(4, CompoundList(Float(grthan=0.0), Point2D())) icheck(5, Float(within=[-1., 180., '[]'])) icheck(6, Float(grthan=0.0)) if not isinstance(ref_conts, list): ref_conts = [ref_conts] rp = [] for i in range(len(ref_pts) / 2): rp.append(ref_pts[2 * i]) rp.extend(ref_pts[2 * i + 1]) args = {"base": cont, "cconts": ref_conts, "cpts": rp, "step": step, "infdist": influence, "angle0": angle0, "power": power } c = com.contcom.MatchedPartition(args) flow.exec_command(c) return c.added_contours2()[0]
def add_circ_rect_grid(p0, rad, step, sqrside=1.0, rcoef=1.0, algo="linear"): """ Creates quadrangular cell grid in a circular area. See details in :ref:`circrect_grid`. :param list-of-floats p0: center point of circle area in [x, y] format. :param positive-float rad: radius of circle area. :param positive-float step: approximate partition step of the outer boundary. :param positive-float sqrside: side of the inner square normalized by the circle radius. Values greater than 1.4 are not allowed. :param positive-float rcoef: radius direction refinement of the ring part of the grid. Values less then unity lead to refinement towards outer boundary. :param str algo: Algorithms of assembling the ring part of the grid. * ``'linear'`` - use weighted approach for each ray partition * ``'laplace'`` - use algebraic mapping for building each 45 degree sector. * ``'orthogonal_circ'`` - build orthogonal grid keeping uniform grid at outer circle * ``'orthogonal_rect'`` - build orthogonal grid keeping uniform grid at inner rectangle :return: new grid identifier """ icheck(0, Point2D()) icheck(1, Float(grthan=0.0)) icheck(2, Float(grthan=0.0)) icheck(3, Float(within=[0., 1.4, '[)'])) icheck(4, Float(grthan=0.0)) icheck(5, OneOf('linear', 'laplace', 'orthogonal_circ', 'orthogonal_rect')) # call args = { 'algo': algo, 'p0': p0, 'rad': rad, 'step': step, 'sqrside': sqrside, 'rcoef': rcoef } c = com.gridcom.AddCirc4Grid(args) flow.exec_command(c) return c.added_grids2()[0]
def add_circ_contour2(p0, p1, p2, n_arc, bnd=0): """Adds circle contour from given arc points. :param list-of-floats p0: :param list-of-floats p1: :param list-of-floats p2: circle arc points as [x, y] format :param int n_arc: partition of circle arc :param bnd: boundary identifier for contour. With the default value no boundary types will be set. :return: Contour identifier """ icheck(0, Point2D()) icheck(1, Point2D(noteq=[p0])) icheck(2, Point2D(noteq=[p0, p1])) icheck(3, UInt(minv=3)) icheck(4, ZType()) p0, p1, p2 = map(float, p0), map(float, p1), map(float, p2) xb, yb = p1[0] - p0[0], p1[1] - p0[1] xc, yc = p2[0] - p0[0], p2[1] - p0[1] A11, A12 = 2.0 * xb, 2.0 * yb A21, A22 = 2.0 * xc, 2.0 * yc B1, B2 = xb * xb + yb * yb, xc * xc + yc * yc d = A11 * A22 - A12 * A21 I11, I12, I21, I22 = A22 / d, -A12 / d, -A21 / d, A11 / d cx = I11 * B1 + I12 * B2 cy = I21 * B1 + I22 * B2 rad = math.sqrt((cx - xb) * (cx - xb) + (cy - yb) * (cy - yb)) return add_circ_contour([cx + p0[0], cy + p0[1]], rad, n_arc, bnd)
def add_unf_ring_grid(p0, radinner, radouter, na, nr, coef=1.0, bnd=0): """Builds ring grid :param list-of-floats p0: center coordinates as [x, y] :param float radinner: :param float radouter: inner and outer radii :param int na: :param int nr: arc and radius partition respectively :param float coef: refinement coefficient: * ``coef = 1``: equidistant radius division * ``coef > 1``: refinement towards center of circle * ``0 < coef < 1``: refinement towards outer arc :param int-or-list-of-int bnd: boundary types for inner and outer ring boundaries :return: created grid identifier """ if radinner > radouter: radinner, radouter = radouter, radinner icheck(0, Point2D()) icheck(1, Float(grthan=0.0)) icheck(2, Float(grthan=0.0)) icheck(3, UInt(minv=3)) icheck(4, UInt(minv=1)) icheck(5, Float(grthan=0.0)) icheck(6, ListOr1(ZType(), llen=2)) bnd = bnd[:2] if isinstance(bnd, list) else [bnd, bnd] c = com.gridcom.AddUnfRingGrid({ "p0": p0, "radinner": radinner, "radouter": radouter, "na": na, "nr": nr, "coef": coef, "bnd": bnd }) flow.exec_command(c) return c.added_grids2()[0]
def rotate_geom(objs, angle, pc=[0.0, 0.0]): """ Rotates group of 2d objects :param objs: identifier or list of identifiers of rotating 2d objects :param float angle: degree of rotation. Positive angle corresponds to counterclockwise rotation :param list-of-float pc: center of rotation :returns: None """ icheck(0, UListOr1(ACont2D())) icheck(1, Float()) icheck(2, Point2D()) ob = objs if isinstance(objs, list) else [objs] c = com.objcom.RotateGeom({"names": ob, "angle": angle, "p0": pc}) flow.exec_command(c)
def pick_contour(pnt, contlist=[]): """ Returns contour closest to given point :param pnt: point as [x, y] list :param contlist: list of contour identifier to choose from :returns: closest contour identifier If **contlist** is empty then looks over all registered contours. This procedure does not take 2d grid contours into account. """ icheck(0, Point2D()) icheck(1, List(ACont2D())) conts = map(flow.receiver.get_any_contour, contlist) cc = closest_contour(conts, pnt) ind = conts.index(cc) return contlist[ind]
def extract_subcontours(source, plist, project_to="vertex"): """ Extracts singly connected subcontours from given contour. :param source: source contour identifier :param list-of-list-of-float plist: consecutive list of subcontours end points :param str project_to: defines projection rule for **plist** entries * ``"line"`` projects to closest point on the source contour * ``"vertex"`` projects to closest contour vertex * ``"corner"`` projects to closest contour corner vertex :returns: list of new contours identifiers Length of **plist** should be equal or greater than two. First and last points in **plist** define first and last points of **source** segment to extract. All internal points define internal division of this segment. Hence number of resulting subcontours will equal number of points in **plist** minus one. For closed **source** contour first and last **plist** points could coincide. In that case the sum of resulting subcontours will be equal to **source**. """ icheck(0, ACont2D()) icheck(1, List(Point2D(), minlen=2)) icheck(2, OneOf("line", "vertex", "corner")) c = com.contcom.ExtractSubcontours({ 'src': source, 'plist': plist, 'project_to': project_to }) flow.exec_command(c) return c.added_contours2()
def create_contour(pnts, bnds=0): """ Create singly connected contour from sequence of points. :param list-of-list-of-floats pnts: sequence of points. If coordinates of first and last points are equal then contour is considered closed. :param single-or-list-of-boundary-identifiers bnds: boundary type for each contour segment or single identifier for the whole contour. :returns: contour identifier Example: >>> hmscript.create_contour([[0, 0], [1, 0], [1, 1], [0, 0]], [b1, b2, b3]) """ icheck(0, List(Point2D(), minlen=2)) icheck(1, ListOr1(ZType())) b = bnds if isinstance(bnds, list) else [bnds] c = com.contcom.CreateContour({"points": pnts, "bnds": b}) flow.exec_command(c) return c.added_contours2()[0]
def triangulate_domain(domain, constr=[], pts=[], fill='3'): """Builds constrained triangulation within given domain :param domain: single or list of closed contours representing bounding domain :param constr: single or list of contours representing triangulation constraints :param pts: set of points in ``[len0, [x0, y0], ...]`` format where ``x, y`` are coordinates of internal vertices which should be embedded into the resulting grid, ``len`` - size of adjacent cells :param str fill: if '3' then triangulates area; '4' runs recombination algorithm to make mostly quadrangular mesh :return: grid identifier A contour tree will be built using all closed contours passed as **domain** parameter. Only the interior parts of this tree will be meshed. Contours passed by **domain** should not intersect each other, but could intersect **constr** contours. **constr** could contain any set of closed and open contours. See details in :ref:`unstructured-meshing`. """ icheck(0, UListOr1(ACont2D())) icheck(1, UListOr1(ACont2D())) icheck(2, CompoundList(Float(grthan=0.0), Point2D())) icheck(3, OneOf('3', '4')) if fill == '3': return _triquad(domain, constr, pts, '3') elif fill == '4': return _triquad(domain, constr, pts, '4')
def revolve_grid(obj, p1, p2, n_phi=None, phi=None, btype1=0, btype2=0, merge_central=False): """ Creates 3D grid by revolution of 2D grid around a vector :param obj: 2d grid identifier :param p1: :param p2: points in [x, y] format which define vector of rotation :param int n_phi: partition along circular coordinate. If this parameter is defined then [0, 360] range will be divided into equal parts and full revolution solid will be build. :param list-of-floats phi: increasing vector defining custom partition of angular range. This parameter will be processed if **n_phi** is None. If the last value of **phi** is not equal to first one plus 360 degree than incomplete revolution solid will be built. :param btype1: :param btype2: boundary identifiers for surfaces which will be build as a result of incomplete rotation at end values of **phi** vector. :param bool merge_central: if rotation vector coincides with boundary edges of input grid then this parameter defines whether central cells derived from the revolution of respective boundary cells should be merged into one complex finite volume (True) or left as they are (False). :returns: 3D grid identifier All points of input grid should lie to the one side of rotation vector. Use :func:`partition_segment` to define non-equidistant **phi** with any desired refinement if needed. """ icheck(0, Grid2D()) icheck(1, Point2D()) icheck(2, Point2D(noteq=p1)) icheck(3, NoneOr(UInt(minv=3))) icheck(4, NoneOr(IncList(Float()))) icheck(5, ZType()) icheck(6, ZType()) icheck(7, Bool()) # calculate phi's if n_phi is None: inp_phi = copy.deepcopy(phi) else: inp_phi = [] for i in range(n_phi + 1): inp_phi.append(360. * i / n_phi) c = com.grid3dcom.Revolve({ "base": obj, "p1": p1, "p2": p2, "phi": inp_phi, "bt1": btype1, "bt2": btype2, "center_tri": not merge_central }) flow.exec_command(c) return c.added_grids3()[0]
def partition_contour(cont, algo, step=1., angle0=30., keep_bnd=False, nedges=None, crosses=[], keep_pts=[], start=None, end=None): """ Makes connected contour partition :param cont: Contour or grid identifier :param str algo: Partition algorithm: * ``'const'``: partition with defined constant step * ``'ref_points'``: partition with step function given by a set of values refered to basic points * ``'ref_weights'``: partition with step function given by a set of values refered to local contour [0, 1] coordinate * ``'ref_lengths'``: partition with step function given by a set of values refered to local contour length coordinate :param step: For ``algo='const'`` a float number defining partition step; For ``algo='ref_points'`` - list of step values and point coordinates given as ``[ step_0, [x_0, y_0], step_1, [x_1, y_1], ....]``. For ``algo='ref_weights'`` - list of step values and point normalized 1d coordinates given as ``[ step_0, w_0, step_1, w_1, ....]``. For ``algo='ref_lengths'`` - list of step values and point 1d coordinates given as ``[ step_0, s_0, step_1, s_1, ....]``. Negative ``s_i`` shows length coordinate started from end point in reversed direction. :param float angle0: existing contour vertices which provide turns outside of ``[180 - angle0, 180 + angle0]`` degrees range will be preserved regardless of other options :param bool keep_bnd: if that is True than vertices which have different boundary features on their right and left sides will be preserved :param int nedges: if this parameter is not None then it provides exact number of edges in the resulting contour. To satisfy this condition **step** value will be multiplied by an appropriate factor. If it can not be satisfied (due to other restrictions) then an exception will be raised. :param crosses: represents set of contour which cross points with target contour will be present in resulting contour. :param keep_pts: list of points as ``[[x1, y1], [x2, y2], ...]`` list which should present in output partition. :param start: :param end: start and end points which define processing segment :returns: new contour identifier Points set defined by user for ``algo='ref_points'`` algorithm will not present in resulting contour (as well as points defined implicitly by other ``'ref_'`` algorithms). It just shows locations where step size of given length should be applied. If any point of this set is not located on the input contour then it will be projected to it. For constant stepping any contour including multiply connected ones could be passed. For ``ref_`` stepping only singly connected contours (open or closed) are allowed. If **start** and **end** points are defined then only segment between these points will be parted. Note that all closed contours are treated in counterclockwise direction. Given start/end points will be projected to closest contour vertices. ``ref_weights``, ``ref_lengths`` partition methods require definition of **start** point (To process whole contour ``end`` point could be omitted). Example: .. literalinclude:: ../../testing/py/fromdoc/ex_partcontour.py :start-after: vvvvvvvvvvvvvvvvvvvvvvvv :end-before: ^^^^^^^^^^^^^^^^^^^^^^^^ See also: :ref:`simplecontmeshing` """ if nedges <= 0: nedges = None icheck(0, ACont2D()) icheck(1, OneOf("const", "ref_points", "ref_weights", "ref_lengths")) if algo == "const": icheck(2, Float(grthan=0.0)) elif algo == "ref_points": icheck(2, CompoundList(Float(grthan=0.0), Point2D(), minlen=2)) elif algo == "ref_weights": icheck(2, CompoundList(Float(grthan=0.0), Float(within=[-1, 1, '[]']), minlen=2)) elif algo == "ref_lengths": icheck(2, CompoundList(Float(grthan=0.0), Float(), minlen=2)) icheck(3, Float()) icheck(4, Bool()) icheck(5, NoneOr(UInt(minv=1))) icheck(6, List(ACont2D())) icheck(7, List(Point2D())) icheck(8, NoneOr(Point2D())) icheck(9, NoneOr(Point2D())) if start is None and algo in ['ref_weights', 'ref_lengths']: raise InvalidArgument("Define start point for %s partition" % algo) # prepare arguments for command if algo == "const": plain_step = [step] elif algo == "ref_points": plain_step = [] for i in range(len(step) / 2): plain_step.append(step[2 * i]) plain_step.extend(step[2 * i + 1]) elif algo in ["ref_weights", "ref_lengths"]: plain_step = copy.deepcopy(step) sp, ep = None, None if start is not None: sp = [start[0], start[1]] if end is not None: ep = [end[0], end[1]] kp = [] if keep_pts is not None: for p in keep_pts: kp.append([p[0], p[1]]) args = {"algo": algo, "step": plain_step, "angle0": angle0, "keepbnd": keep_bnd, "base": cont, "nedges": nedges, "crosses": crosses, "start": sp, "end": ep, "keep_pts": kp} # call c = com.contcom.PartitionContour(args) flow.exec_command(c) return c.added_contours2()[0]
def add_unf_rect_grid(p0=[0, 0], p1=[1, 1], nx=3, ny=3, custom_x=[], custom_y=[], bnd=0): """Builds rectangular grid. :param list-of-floats p0: :param list-of-floats p1: bottom left, top right points in [x, y] format. :param int nx: :param int ny: partition in x and y directions. :param float-or-list-of-floats custom_x: :param float-or-list-of-floats custom_y: custom x and y coordinates :param int-or-list-of-int: boundary types for bottom, right, top, left rectangle sides :returns: created grid identifier Builds a grid in a rectangular area formed by points **p0** and **p1**. **nx** and **ny** provide grid partition in x and y direction. If **custom_x**/**custom_y** is given by a single float value than it shows a step size in respective direction, hence values given by **nx**/**ny** parameters will be omitted. If **custom_x**/**custom_y** is given by a list of increasing floats it explicitly shows the partition in respective direction. In the latter case the respective **p0**, **p1** coordinates will also be ignored. Use :func:`partition_segment` to conveniently define **custom\_** fields if needed. """ icheck(0, Point2D()) icheck(1, Point2D(grthan=p0)) icheck(2, UInt(minv=1)) icheck(3, UInt(minv=1)) icheck(4, Or(Float(grthan=0.), IncList(Float()))) icheck(5, Or(Float(grthan=0.), IncList(Float()))) icheck(6, ListOr1(ZType(), llen=4)) bnd = bnd[:4] if isinstance(bnd, list) else [bnd, bnd, bnd, bnd] custom_x = custom_x if isinstance(custom_x, list) else [custom_x] custom_y = custom_y if isinstance(custom_y, list) else [custom_y] c = com.gridcom.AddUnfRectGrid({ "p0": p0, "p1": p1, "nx": nx, "ny": ny, "custom_x": custom_x, "custom_y": custom_y, "bnds": bnd }) flow.exec_command(c) return c.added_grids2()[0]
def add_unf_circ_grid(p0, rad=1.0, na=8, nr=4, coef=1.0, is_trian=True, custom_rads=[], custom_arcs=[], bnd=0): """Builds circular grid. :param list-of-floats p0: center coordinate as [x, y] :param float rad: radius :param int na: :param int nr: partitions of arc and radius respectively :param float coef: refinement coefficient: * ``coef = 1``: equidistant radius division * ``coef > 1``: refinement towards center of circle * ``0 < coef < 1``: refinement towards outer arc :param bool is_trian: True if center cell should be triangulated :param float-or-list-of-floats custom_rads: user defined radious partition :param float-or-list-of-floats custom_arcs: user defined arc partition :param int bnd: boundary type for outer contour :returns: created grid identifier Creates a radial grid with the center in **p0**. If **custom_rads** is given as a single value it will be used as a constant step along radial axis hence **nr** and **coef** arguments will be ignored. If it is given as a list of increasing values starting from zero then it is parsed as explicit radius partition. Hence the last entry of this list will be the radius of the resulting grid and **rad** parameter will also be ignored. If **custom_arcs** is given as a single value it shows the constant step along outer arc and **na** will be ignored. If it is an increasing list of floats, it shows partition of outer arc. It can be given in degrees or radians or any other relative units. Program treats **custom_arcs[-1]**-**custom_arcs[0]** difference as a full circle length and normalizes all other entries to this length. First and last entries of this array provides the same arc segment (last = first + 2*pi) hence to get partition of n segments you should define n+1 entries. Use :func:`partition_segment` to conveniently define **custom\_** fields if needed. """ icheck(0, Point2D()) icheck(1, Float(grthan=0.0)) icheck(2, UInt(minv=3)) icheck(3, UInt(minv=1)) icheck(4, Float(grthan=0.0)) icheck(5, Bool()) icheck(6, Or(Float(grthan=0.0), IncList(Float()))) icheck(7, Or(Float(grthan=0.0), IncList(Float()))) icheck(8, ZType()) custom_rads = custom_rads if isinstance(custom_rads, list)\ else [custom_rads] custom_arcs = custom_arcs if isinstance(custom_arcs, list)\ else [custom_arcs] c = com.gridcom.AddUnfCircGrid({ "p0": p0, "rad": rad, "na": na, "nr": nr, "coef": coef, "is_trian": is_trian, "custom_r": custom_rads, "custom_a": custom_arcs, "bnd": bnd }) flow.exec_command(c) return c.added_grids2()[0]
def get_point(obj, ind=None, vclosest=None, eclosest=None, cclosest=None, only_contour=True): """ Returns object point :param obj: grid or contour identifier :param int ind: index of point :param vclosest: :param eclosest: :param cclosest: point as [x, y] list :param bool only_contour: If that is true then if **objs** is a grid then respective grid contour will be used :returns: point as [x, y] list Only one of **ind**, **vclosest**, **eclosest**, **cclosest** arguments should be defined. If **ind** is defined then returns point at given index. If **vvlosest** point is defined then returns object vertex closest to this point. If **eclosest** point is defined then returns point owned by an object edge closest to input point. If **cclosest** point is defined then returns non straight line object contour vertex closest to input point. """ icheck(0, ACont2D()) icheck(1, NoneOr(UInt())) icheck(2, NoneOr(Point2D())) icheck(3, NoneOr(Point2D())) icheck(4, NoneOr(Point2D())) icheck(5, Bool()) if ind is None and vclosest is None and eclosest is None and\ cclosest is None: raise InvalidArgument("Define point location") try: tar = flow.receiver.get_contour2(obj) except KeyError: tar = flow.receiver.get_grid2(obj) if only_contour or cclosest is not None: tar = tar.contour() if cclosest is not None: tar = tar.deepcopy() c2core.simplify(tar.cdata, 0, False) vclosest = cclosest if vclosest is not None: return tar.closest_points([vclosest], "vertex")[0] elif eclosest is not None: return tar.closest_points([eclosest], "edge")[0] elif ind is not None: return tar.point_at(ind)