Beispiel #1
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]
Beispiel #2
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]
Beispiel #3
0
def set_btypes(obj, bt, segm=None):
    icheck(0, AObject())
    icheck(1, ZType())
    icheck(2, NoneOr(List(UInt())))
    if segm is None:
        generalfun.set_boundary_type(obj, bt)
    else:
        generalfun.set_boundary_type(obj, bdict={bt: segm})
Beispiel #4
0
def unite_contours(conts):
    """ Unites contours to single multiply connected contour

    :param conts: list of contours identifiers to unite

    :return: contour identifier

    Equal nodes and segments of input contours will be merged.
    """
    icheck(0, List(ACont2D()))

    c = com.contcom.UniteContours({"sources": conts})
    flow.exec_command(c)
    return c.added_contours2()[0]
Beispiel #5
0
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]
Beispiel #6
0
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()
Beispiel #7
0
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]
Beispiel #8
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]
Beispiel #9
0
def set_boundary_type(obj, btps=None, bfun=None, bdict=None):
    """ Mark geometrical object with boundary types.

    :param obj: geometric object identifier

    :param btps: single identifier for the whole object or list
       of identifiers for each boundary segment.

    :param  bfun: function which returns boundary type taking segment
       coordinates and old boundary type as arguments.

    :param bdict: {btype: [list-of-segment indicies]} dictionary
       which maps boundary type with object segments indicies

    Only one of **btps**, **bfun**, **bdict** arguments should be defined.

    **bfun** signature is:

       * ``(x0, y0, x1, y1, bt) -> btype`` for 2D objects, where
         *x0, y0, x1, y1* are edge end point coordinates,
         bt - old boundary type
       * ``(xc, yc, zc, bt) -> btype`` for 3D objects, where
         *xc, yc, zc* - approximate face center coordinates,
         bt - old boundary type

    If **obj** is a grid then only boundary segments will be passed
    to **bfun** function and **btps** list entries will
    be associated with boundary segments only.
    However **bdict** entries should contain global edge or face indicies.

    Example:

      .. literalinclude:: ../../testing/py/fromdoc/ex_setbtype.py
          :start-after: START OF EXAMPLE
          :end-before: END OF EXAMPLE

    """
    icheck(0, AObject())
    icheck(1, NoneOr(ListOr1(ZType())))
    icheck(3, NoneOr(Dict(ZType(), List(UInt()))))
    t = flow.receiver.whatis(obj)
    if t in ['g2', 'c2']:
        icheck(2, NoneOr(Func(narg=5)))
    else:
        icheck(2, NoneOr(Func(narg=4)))
    if [btps, bfun, bdict].count(None) != 2:
        raise InvalidArgument("One of [btps, bfun, bdict] should be not None")

    args = {'name': obj, 'whole': None, 'btypes': {}}

    if isinstance(btps, int):
        args['whole'] = btps
    elif bdict is not None:
        args['btypes'] = bdict
    else:
        g = flow.receiver.get_object(obj)
        if t == 'g2':
            if btps is not None:
                _setbt_args_g2g3btps(g, btps, args['btypes'])
            if bfun is not None:
                _setbt_args_g2bfun(g, bfun, args['btypes'])
        if t == 'g3':
            if btps is not None:
                _setbt_args_g2g3btps(g, btps, args['btypes'])
            if bfun is not None:
                _setbt_args_g3bfun(g, bfun, args['btypes'])
        if t == 'c2':
            if btps is not None:
                _setbt_args_c2s3btps(g, btps, args['btypes'])
            if bfun is not None:
                _setbt_args_c2bfun(g, bfun, args['btypes'])
        if t == 's3':
            if btps is not None:
                _setbt_args_c2s3btps(g, btps, args['btypes'])
            if bfun is not None:
                _setbt_args_s3bfun(g, bfun, args['btypes'])
    c = com.objcom.SetBType(args)
    flow.exec_command(c)
Beispiel #10
0
def add_custom_rect_grid(algo,
                         left,
                         bottom,
                         right=None,
                         top=None,
                         hermite_tfi_w=[1.0, 1.0, 1.0, 1.0],
                         return_invalid=False):
    """ Creates rectangular grid on the basis of four curvilinear contours
    using contour vertices for partition.
    See details in :ref:`custom_rect_grid`.

    :param str algo: Algorithms of building:

       * ``'linear'`` - connects respective points of opposite
         contours by straight lines.
       * ``'linear_tfi'`` - linear transfinite interpolation
       * ``'hermite_tfi'`` - hermite transfinite interpolation
       * ``'inverse_laplace'`` -
       * ``'direct_laplace'`` - connects points using solution of
         laplace equation with Dirichlet boundary conditions;
       * ``'orthogonal'`` - builds orthogonal grid based on **left** and
         **bottom** partition.
         Partitions of **right** and **top** are ignored.

    :param left:

    :param bottom:

    :param right:

    :param top: identifiers of curvilinear domain sides.
       **right** and **top** could be ``None``. If so right and top
       boundaries will be created by translation of **left** and **bottom**.

    :param list-of-floats hermite_tfi_w:
       perpendicularity weights
       for **left**, **bottom**, **right**, **top** contours respectively
       for **algo** = ``'hermite_tfi'``

    :param bool return_invalid: if this flag is on
       then the procedure will return a grid even if it is not valid
       (has self-intersections). Such grids could be exported to
       simple formats (like vtk or tecplot) in order to detect
       bad regions and give user a hint of how to adopt
       input data to gain an acceptable result.

       .. warning:: Never use invalid grids for further operations.

    :return: new grid identifier

    """
    icheck(
        0,
        OneOf('linear', 'linear_tfi', 'hermite_tfi', 'inverse_laplace',
              'direct_laplace', 'orthogonal'))
    icheck(1, Cont2D())
    icheck(2, Cont2D())
    icheck(3, NoneOr(Cont2D()))
    icheck(4, NoneOr(Cont2D()))
    icheck(5, List(Float(), llen=4))
    icheck(6, Bool())

    # call
    args = {
        'algo': algo,
        'left': left,
        'right': right,
        'bot': bottom,
        'top': top,
        'her_w': hermite_tfi_w,
        'return_invalid': return_invalid
    }
    c = com.gridcom.AddCustomRectGrid(args)
    flow.exec_command(c)
    return c.added_grids2()[0]