示例#1
0
def generate_ifc_cylinder_geom(shape: PrimCyl, f):
    """Create IfcExtrudedAreaSolid from primitive PrimCyl"""
    p1 = shape.p1
    p2 = shape.p2
    r = shape.r

    vec = np.array(p2) - np.array(p1)
    uvec = unit_vector(vec)
    vecdir = to_real(uvec)

    cr_dir = np.array([0, 0, 1])

    if vector_length(abs(uvec) - abs(cr_dir)) == 0.0:
        cr_dir = np.array([1, 0, 0])

    perp_dir = np.cross(uvec, cr_dir)

    if vector_length(perp_dir) == 0.0:
        raise ValueError("Perpendicular dir cannot be zero")

    create_ifc_placement(f, to_real(p1), vecdir, to_real(perp_dir))

    opening_axis_placement = create_ifc_placement(f, to_real(p1), vecdir,
                                                  to_real(perp_dir))

    depth = vector_length(vec)
    profile = f.createIfcCircleProfileDef("AREA", shape.name, None, r)
    return create_ifcextrudedareasolid(f, profile, opening_axis_placement, Z,
                                       depth)
示例#2
0
    def calc_con_points(self, point_tol=Settings.point_tol):
        from ada.core.vector_utils import sort_points_by_dist

        a = self.n1.p
        b = self.n2.p
        points = [tuple(con.centre) for con in self.connected_to]

        def is_mem_eccentric(mem, centre):
            is_ecc = False
            end = None
            if point_tol < vector_length(mem.n1.p - centre) < mem.length * 0.9:
                is_ecc = True
                end = mem.n1.p
            if point_tol < vector_length(mem.n2.p - centre) < mem.length * 0.9:
                is_ecc = True
                end = mem.n2.p
            return is_ecc, end

        if len(self.connected_to) == 1:
            con = self.connected_to[0]
            if con.main_mem == self:
                for m in con.beams:
                    if m != self:
                        is_ecc, end = is_mem_eccentric(m, con.centre)
                        if is_ecc:
                            logging.info(f'do something with end "{end}"')
                            points.append(tuple(end))

        midpoints = []
        prev_p = None
        for p in sort_points_by_dist(a, points):
            p = np.array(p)
            bmlen = self.length
            vlena = vector_length(p - a)
            vlenb = vector_length(p - b)

            if prev_p is not None:
                if vector_length(p - prev_p) < point_tol:
                    continue

            if vlena < point_tol:
                self._connected_end1 = self.connected_to[points.index(
                    tuple(p))]
                prev_p = p
                continue

            if vlenb < point_tol:
                self._connected_end2 = self.connected_to[points.index(
                    tuple(p))]
                prev_p = p
                continue

            if vlena > bmlen or vlenb > bmlen:
                prev_p = p
                continue

            midpoints += [p]
            prev_p = p

        return midpoints
示例#3
0
 def is_mem_eccentric(mem, centre):
     is_ecc = False
     end = None
     if point_tol < vector_length(mem.n1.p - centre) < mem.length * 0.9:
         is_ecc = True
         end = mem.n1.p
     if point_tol < vector_length(mem.n2.p - centre) < mem.length * 0.9:
         is_ecc = True
         end = mem.n2.p
     return is_ecc, end
示例#4
0
def test_3d_input(dummy_display):
    pl1 = ada.Plate("MyPl", [(0, 0, 0), (5, 0, 0), (5, 5, 0), (0, 5, 0)], 20e-3, use3dnodes=True)
    origin = np.array([0, 0, 0])

    assert vector_length(pl1.placement.origin - origin) < 1e-8
    assert vector_length(pl1.placement.zdir - np.array([0, 0, 1])) < 1e-8
    assert vector_length(pl1.poly.nodes[0].p - origin) < 1e-8

    assert_points = [(0.0, 0.0), (5.0, 0.0), (5.0, -5.0), (0.0, -5.0)]

    for i, (x, y) in enumerate(pl1.poly.points2d):
        x_, y_ = assert_points[i]
        assert x_ == x and y_ == y

    dummy_display(pl1)
示例#5
0
def import_straight_beam(ifc_elem, axis, name, sec, mat, ifc_ref: IfcRef,
                         assembly: Assembly) -> Beam:
    p1_loc = axis.Points[0].Coordinates
    p2_loc = axis.Points[1].Coordinates

    ifc_axis_2_place3d = ifc_elem.ObjectPlacement.RelativePlacement
    origin = ifc_axis_2_place3d.Location.Coordinates

    local_z = np.array(ifc_axis_2_place3d.Axis.DirectionRatios)
    local_x = np.array(ifc_axis_2_place3d.RefDirection.DirectionRatios)
    local_y = calc_yvec(local_x, local_z)

    # res = transform3d([local_x, local_y, local_z], [X, Y], origin, [p1_loc, p2_loc])
    vlen = vector_length(np.array(p2_loc) - np.array(p1_loc))

    p1 = origin
    p2 = np.array(p1) + local_z * vlen

    return Beam(name,
                p1,
                p2,
                sec=sec,
                mat=mat,
                up=local_y,
                guid=ifc_elem.GlobalId,
                ifc_ref=ifc_ref,
                units=assembly.units)
示例#6
0
    def add(self,
            node: Node,
            point_tol: float = Settings.point_tol,
            allow_coincident: bool = False) -> Node:
        """Insert node into sorted list"""
        def insert_node(n, i):
            new_id = int(self._maxid + 1) if len(self._nodes) > 0 else 1
            if n.id in self._idmap.keys() or n.id is None:
                n.id = new_id

            self._nodes.insert(i, n)
            self._idmap[n.id] = n
            self._bbox = None
            self._maxid = n.id if n.id > self._maxid else self._maxid

        index = bisect_left(self._nodes, node)
        if (len(self._nodes) != 0) and allow_coincident is False:
            res = self.get_by_volume(node.p, tol=point_tol)
            if len(res) == 1:
                nearest_node = res[0]
                vlen = vector_length(nearest_node.p - node.p)
                if vlen < point_tol:
                    logging.debug(
                        f'Replaced new node with node id "{nearest_node.id}" found within point tolerances'
                    )
                    return nearest_node

        insert_node(node, index)

        if node.parent is None:
            node.parent = self.parent

        return node
示例#7
0
def test_floaty_input_ex1():
    origin = [362237.0037951513, 100000.0, 560985.9095763591]
    csys = [
        [0.0, -1.0, 0.0],
        [-0.4626617625735456, 0.0, 0.8865348799975894],
        [-0.8865348799975894, 0.0, -0.4626617625735456],
    ]
    local_points2d = [
        [4.363213751783499e-11, 229.80445306040926],
        [1.4557793281525672e-11, -57.217605078163196],
        [2.912511939794014e-11, -207.22885580839431],
        [-330.0, -207.25, -4.518217213237464e-11],
        [-400.0, -122.2, 50.0],
        [-400.0, 42.79, 50.0],
        [-325.0, 267.83, 50.0],
        [-85.00004587126028, 650.0198678083951, 24.999999999931404],
        [-35.0, 650.02, -7.881391015070461e-12],
        [-35.0, 350.1],
        [-15.14, 261.52],
    ]
    thick = 30
    pl = ada.Plate(
        "test", local_points2d, thick, placement=ada.Placement(origin=origin, zdir=csys[2], xdir=csys[0]), units="mm"
    )
    assert tuple(pl.placement.origin) == tuple(origin)
    assert tuple(pl.placement.zdir) == tuple(csys[2])
    assert vector_length(pl.nodes[0].p - np.array([362130.68206185, 100000.0, 561189.63923958])) < 1e-8
示例#8
0
    def add_geom(self, geom, obj, geom_repr=None):
        from ada.concepts.transforms import Placement
        from ada.core.vector_utils import vector_length

        from .utils import transform_shape

        name = obj.name if obj.name is not None else next(shp_names)
        Interface_Static_SetCVal("write.step.product.name", name)

        # Transform geometry
        res = obj.placement.absolute_placement()
        if vector_length(res - Placement().origin) > 0:
            geom = transform_shape(geom, transform=tuple(res))
        try:
            if geom_repr == ElemType.SHELL:
                stat = self.writer.Transfer(
                    geom, STEPControl_ShellBasedSurfaceModel)
            else:
                stat = self.writer.Transfer(geom, STEPControl_AsIs)
        except BaseException as e:
            logging.info(f"Passing {obj} due to {e}")
            return None

        if int(stat) > int(IFSelect_RetError):
            raise Exception("Some Error occurred")

        item = stepconstruct_FindEntity(self.fp, geom)
        if not item:
            logging.debug("STEP item not found for FindEntity")
        else:
            item.SetName(TCollection_HAsciiString(name))
示例#9
0
    def __eq__(self, other: Placement):
        from ada.core.vector_utils import vector_length

        for prop in ["origin", "xdir", "ydir", "zdir"]:
            if vector_length(getattr(other, prop) - getattr(self, prop)) > 0.0:
                return False

        return True
示例#10
0
        def calc_bm_elem(el: Elem):
            nodes_ = el.get_offset_coords()
            elem_len = vector_length(nodes_[-1] - nodes_[0])
            vol_ = el.fem_sec.section.properties.Ax * elem_len
            mass = vol_ * el.fem_sec.material.model.rho
            center = sum([e.p for e in el.nodes]) / len(el.nodes)

            return mass, center, vol_
示例#11
0
    def length(self) -> float:
        """Returns the length of the beam"""
        p1 = self.n1.p
        p2 = self.n2.p

        if self.e1 is not None:
            p1 += self.e1
        if self.e2 is not None:
            p2 += self.e2
        return vector_length(p2 - p1)
示例#12
0
文件: utils.py 项目: Krande/adapy
def get_bm_sections(model: gmsh.model, beam: Beam, gmsh_data, fem: FEM):
    from ada.core.vector_utils import vector_length

    tags = []
    for dim, ent in gmsh_data.entities:
        _, tag, _ = model.mesh.getElements(1, ent)
        tags += tag

    elements = [
        fem.elements.from_id(elid) for elid in chain.from_iterable(tags)
    ]

    set_name = make_name_fem_ready(f"el{beam.name}_set_bm")
    fem_sec_name = make_name_fem_ready(f"d{beam.name}_sec_bm")
    fem_set = FemSet(set_name, elements, FemSet.TYPES.ELSET, parent=fem)
    fem_sec = FemSection(fem_sec_name,
                         ElemType.LINE,
                         fem_set,
                         beam.material,
                         beam.section,
                         beam.ori[2],
                         refs=[beam])

    add_sec_to_fem(fem, fem_sec, fem_set)
    if beam.hinge_prop is None:
        return
    end1_p = beam.hinge_prop.end1.concept_node.p if beam.hinge_prop.end1 is not None else None
    end2_p = beam.hinge_prop.end2.concept_node.p if beam.hinge_prop.end2 is not None else None
    if beam.hinge_prop is not None:
        for el in elements:
            n1 = el.nodes[0]
            n2 = el.nodes[-1]
            el.hinge_prop = beam.hinge_prop
            if beam.hinge_prop.end1 is not None and vector_length(end1_p -
                                                                  n1.p) == 0.0:
                el.hinge_prop.end1.fem_node = n1

            if beam.hinge_prop.end2 is not None and vector_length(end2_p -
                                                                  n2.p) == 0.0:
                el.hinge_prop.end2.fem_node = n2
示例#13
0
def read_line_section(elem: Elem, fem: FEM, mat: Material, geono, d, lcsysd,
                      hinges_global, eccentricities):
    transno = str_to_int(d["transno"])
    sec = fem.parent.sections.get_by_id(geono)
    n1, n2 = elem.nodes
    v = n2.p - n1.p
    if vector_length(v) == 0.0:
        xvec = [1, 0, 0]
    else:
        xvec = unit_vector(v)
    zvec = lcsysd[transno]
    crossed = np.cross(zvec, xvec)
    ma = max(abs(crossed))
    yvec = tuple([roundoff(x / ma, 3) for x in crossed])

    fix_data = str_to_int(d["fixno"])
    ecc_data = str_to_int(d["eccno"])

    members = None
    if d["members"] is not None:
        members = [
            str_to_int(x) for x in d["members"].replace("\n", " ").split()
        ]

    if fix_data == -1:
        add_hinge_prop_to_elem(elem, members, hinges_global, xvec, yvec)

    if ecc_data == -1:
        add_ecc_to_elem(elem, members, eccentricities, fix_data)

    fem_set = FemSet(sec.name, [elem],
                     "elset",
                     metadata=dict(internal=True),
                     parent=fem)
    fem.sets.add(fem_set, append_suffix_on_exist=True)
    fem_sec = FemSection(
        sec_id=geono,
        name=sec.name,
        sec_type=ElemType.LINE,
        elset=fem_set,
        section=sec,
        local_z=zvec,
        local_y=yvec,
        material=mat,
        parent=fem,
    )
    return fem_sec
示例#14
0
    def local_z(self) -> np.ndarray:
        """Local Z describes the up vector of the cross section"""
        if self._local_z is not None:
            return self._local_z

        if self.type == ElemType.LINE:
            n1, n2 = self.elset.members[0].nodes[0], self.elset.members[0].nodes[-1]
            v = n2.p - n1.p
            if vector_length(v) == 0.0:
                logging.error(f"Element {self.elset.members[0].id} has zero length")
                xvec = [1, 0, 0]
            else:
                xvec = unit_vector(v)
            self._local_z = calc_zvec(xvec, self.local_y)
        elif self.type == ElemType.SHELL:
            self._local_z = normal_to_points_in_plane([n.p for n in self.elset.members[0].nodes])
        else:
            from ada.core.constants import Z

            self._local_z = np.array(Z, dtype=float)

        return self._local_z
示例#15
0
    def _init_orientation(self, angle=None, up=None) -> None:
        xvec = unit_vector(self.n2.p - self.n1.p)
        tol = 1e-3
        zvec = calc_zvec(xvec)
        gup = np.array(zvec)

        if up is None:
            if angle != 0.0 and angle is not None:
                from pyquaternion import Quaternion

                my_quaternion = Quaternion(axis=xvec, degrees=angle)
                rot_mat = my_quaternion.rotation_matrix
                up = np.array([
                    roundoff(x) if abs(x) != 0.0 else 0.0
                    for x in np.matmul(gup, np.transpose(rot_mat))
                ])
            else:
                up = np.array(
                    [roundoff(x) if abs(x) != 0.0 else 0.0 for x in gup])
            yvec = calc_yvec(xvec, up)
        else:
            if (len(up) == 3) is False:
                raise ValueError("Up vector must be length 3")
            if vector_length(xvec - up) < tol:
                raise ValueError(
                    "The assigned up vector is too close to your beam direction"
                )
            yvec = calc_yvec(xvec, up)
            # TODO: Fix improper calculation of angle (e.g. xvec = [1,0,0] and up = [0,1,0] should be 270?
            rad = angle_between(up, yvec)
            angle = np.rad2deg(rad)
            up = np.array(up)

        # lup = np.cross(xvec, yvec)
        self._xvec = xvec
        self._yvec = np.array([roundoff(x) for x in yvec])
        self._up = up
        self._angle = angle
示例#16
0
    def local_y(self) -> np.ndarray:
        """Local y describes the cross vector of the beams X and Z axis"""
        if self._local_y is not None:
            return self._local_y

        if self.type == ElemType.LINE:
            el = self.elset.members[0]
            n1, n2 = el.nodes[0], el.nodes[-1]
            v = n2.p - n1.p
            if vector_length(v) == 0.0:
                raise ValueError(f'Element "{el}" has no length. UNable to calculate y-vector')

            xvec = unit_vector(v)

            # See https://en.wikipedia.org/wiki/Cross_product#Coordinate_notation for order of cross product
            vec = calc_yvec(xvec, self.local_z)
        elif self.type == ElemType.SHELL:
            vec = calc_yvec(self.local_x, self.local_z)
        else:
            vec = calc_yvec(self.local_x, self.local_z)

        self._local_y = np.where(abs(vec) == 0, 0, vec)

        return self._local_y
示例#17
0
    def build_constraint(n_old, elem, ecc, i):
        n_new = edited_nodes[n_old.id]
        mat = np.eye(3)
        new_p = np.dot(mat, ecc) + n_old.p
        n_new_ = Node(new_p, parent=elem.parent)
        if vector_length(n_new_.p - n_new.p) > tol:
            elem.parent.nodes.add(n_new_, allow_coincident=True)
            m_set = FemSet(f"el{elem.id}_mpc{i + 1}_m", [n_new_], "nset")
            s_set = FemSet(f"el{elem.id}_mpc{i + 1}_s", [n_old], "nset")
            c = Constraint(
                f"el{elem.id}_mpc{i + 1}_co",
                Constraint.TYPES.MPC,
                m_set,
                s_set,
                mpc_type="Beam",
                parent=elem.parent,
            )
            elem.parent.add_constraint(c)
            elem.nodes[i] = n_new_
            edited_nodes[n_old.id] = n_new_

        else:
            elem.nodes[i] = n_new
            edited_nodes[n_old.id] = n_new
示例#18
0
def sort_nodes_by_distance(point: Union[Node, np.ndarray],
                           nodes: list[Node]) -> list[Node]:
    if isinstance(point, Node):
        point = point.p
    return sorted(nodes, key=lambda x: vector_length(x.p - point))
示例#19
0
def make_cylinder_from_points(p1, p2, r, t=None):
    vec = unit_vector(np.array(p2) - np.array(p1))
    l = vector_length(np.array(p2) - np.array(p1))
    return make_cylinder(p1, vec, l, r, t)
示例#20
0
文件: piping.py 项目: Krande/adapy
    def _build_pipe(self):
        from ada.core.curve_utils import make_arc_segment

        segs = []
        for p1, p2 in zip(self.points[:-1], self.points[1:]):
            if vector_length(p2.p - p1.p) == 0.0:
                logging.info("skipping zero length segment")
                continue
            segs.append([p1, p2])
        segments = segs

        seg_names = Counter(prefix=self.name + "_")

        # Make elbows and adjust segments
        props = dict(section=self.section,
                     material=self.material,
                     parent=self,
                     units=self.units)
        angle_tol = 1e-1
        len_tol = _Settings.point_tol if self.units == "m" else _Settings.point_tol * 1000
        for i, (seg1, seg2) in enumerate(zip(segments[:-1], segments[1:])):
            p11, p12 = seg1
            p21, p22 = seg2
            vlen1 = vector_length(seg1[1].p - seg1[0].p)
            vlen2 = vector_length(seg2[1].p - seg2[0].p)

            if vlen1 < len_tol or vlen2 == len_tol:
                logging.error(
                    f'Segment Length is below point tolerance for unit "{self.units}". Skipping'
                )
                continue

            xvec1 = unit_vector(p12.p - p11.p)
            xvec2 = unit_vector(p22.p - p21.p)
            a = angle_between(xvec1, xvec2)
            res = True if abs(abs(a) - abs(np.pi)) < angle_tol or abs(
                abs(a) - 0.0) < angle_tol else False

            if res is True:
                self._segments.append(
                    PipeSegStraight(next(seg_names), p11, p12, **props))
            else:
                if p12 != p21:
                    logging.error("No shared point found")

                if i != 0 and len(self._segments) > 0:
                    pseg = self._segments[-1]
                    prev_p = (pseg.p1.p, pseg.p2.p)
                else:
                    prev_p = (p11.p, p12.p)
                try:
                    seg1, arc, seg2 = make_arc_segment(
                        prev_p[0], prev_p[1], p22.p,
                        self.pipe_bend_radius * 0.99)
                except ValueError as e:
                    logging.error(
                        f"Error: {e}"
                    )  # , traceback: "{traceback.format_exc()}"')
                    continue
                except RuntimeError as e:
                    logging.error(
                        f"Error: {e}"
                    )  # , traceback: "{traceback.format_exc()}"')
                    continue

                if i == 0 or len(self._segments) == 0:
                    self._segments.append(
                        PipeSegStraight(next(seg_names),
                                        Node(seg1.p1, units=self.units),
                                        Node(seg1.p2, units=self.units),
                                        **props))
                else:
                    if len(self._segments) == 0:
                        continue
                    pseg = self._segments[-1]
                    pseg.p2 = Node(seg1.p2, units=self.units)

                self._segments.append(
                    PipeSegElbow(
                        next(seg_names) + "_Elbow",
                        Node(seg1.p1, units=self.units),
                        Node(p21.p, units=self.units),
                        Node(seg2.p2, units=self.units),
                        arc.radius,
                        **props,
                        arc_seg=arc,
                    ))
                self._segments.append(
                    PipeSegStraight(next(seg_names),
                                    Node(seg2.p1, units=self.units),
                                    Node(seg2.p2, units=self.units), **props))
示例#21
0
def visualize_it(res_file, temp_dir=".temp", default_index=0):
    import pathlib

    import meshio
    from ipygany import ColorBar, IsoColor, PolyMesh, Scene, Warp, colormaps
    from IPython.display import clear_output, display
    from ipywidgets import AppLayout, Dropdown, FloatSlider, VBox, jslink

    from ada.core.vector_utils import vector_length

    res_file = pathlib.Path(res_file).resolve().absolute()
    suffix = res_file.suffix.lower()

    suffix_map = {".rmed": "med", ".vtu": None}

    imesh = meshio.read(res_file, file_format=suffix_map[suffix])
    imesh.point_data = {
        key.replace(" ", "_"): value
        for key, value in imesh.point_data.items()
    }

    def filter_keys(var):
        if suffix == ".vtu" and var != "U":
            return False
        if suffix == ".rmed" and var == "point_tags":
            return False
        return True

    warp_data = [key for key in filter(filter_keys, imesh.point_data.keys())]
    magn_data = []
    for d in warp_data:
        res = [vector_length(v[:3]) for v in imesh.point_data[d]]
        res_norm = [r / max(res) for r in res]
        magn_data_name = f"{d}_magn"
        imesh.point_data[magn_data_name] = np.array(res_norm, dtype=np.float64)
        magn_data.append(magn_data_name)

    imesh.field_data = {
        key: np.array(value)
        for key, value in imesh.field_data.items()
    }

    tf = (pathlib.Path(temp_dir).resolve().absolute() /
          res_file.name).with_suffix(".vtu")

    if tf.exists():
        os.remove(tf)
    os.makedirs(tf.parent, exist_ok=True)
    imesh.write(tf)

    mesh = PolyMesh.from_vtk(str(tf))
    mesh.default_color = "gray"

    warp_vec = warp_data[default_index]
    try:
        colored_mesh = IsoColor(mesh,
                                input=magn_data[default_index],
                                min=0.0,
                                max=1.0)
    except KeyError as e:
        trace_str = traceback.format_exc()
        logging.error(f'KeyError "{e}"\nTrace: "{trace_str}"')
        colored_mesh = mesh
    except ImportError as e:
        trace_str = traceback.format_exc()
        logging.error("This might be")
        logging.error(f'ImportError "{e}"\nTrace: "{trace_str}"')
        return

    warped_mesh = Warp(colored_mesh, input=warp_vec, warp_factor=0.0)

    warp_slider = FloatSlider(value=0.0, min=-1.0, max=1.0)

    jslink((warped_mesh, "factor"), (warp_slider, "value"))

    # Create a colorbar widget
    colorbar = ColorBar(colored_mesh)

    # Colormap choice widget
    colormap = Dropdown(options=colormaps, description="colormap:")

    jslink((colored_mesh, "colormap"), (colormap, "index"))

    # EigenValue choice widget
    eig_map = Dropdown(options=warp_data, description="Data Value:")

    scene = Scene([warped_mesh])
    app = AppLayout(left_sidebar=scene,
                    right_sidebar=VBox(
                        (eig_map, warp_slider, colormap, colorbar)),
                    pane_widths=[2, 0, 1])

    def change_input(change):
        vec_name = change["new"]
        logging.info(vec_name)
        colored_mesh.input = vec_name + "_magn"
        warped_mesh.input = vec_name
        # Highly inefficient but likely needed due to bug https://github.com/QuantStack/ipygany/issues/69
        clear_output()
        display(app)

    eig_map.observe(change_input, names=["value"])

    return app