Exemple #1
0
    def delete_layout(self, name: str) -> None:
        """
        Delete paper space layout `name` and all entities owned by this layout. Available only for DXF R2000 or later,
        DXF R12 supports only one paperspace and it can't be deleted.

        """
        if name not in self.layouts:
            raise DXFValueError("Layout '{}' does not exist.".format(name))
        else:
            self.layouts.delete(name)
Exemple #2
0
 def _parse_list(self, tags: Iterable[Tuple]) -> List:
     data = list(tags)
     content = []
     for code, value in data[2:-1]:
         factory = self.converter.get(code)
         if factory:
             content.append(factory(value))
         else:
             raise DXFValueError(f"unsupported group code: {code}")
     return content
Exemple #3
0
 def new_line(
         angle: float = 0.,
         base_point: Tuple[float, float] = (0., 0.),
         offset: Tuple[float, float] = (0., 0.),
         dash_length_items: List[float] = None) -> 'PatternDefinitionLine':
     if dash_length_items is None:
         raise DXFValueError(
             "Parameter 'dash_length_items' must not be None.")
     return PatternDefinitionLine(angle, base_point, offset,
                                  dash_length_items)
Exemple #4
0
    def grid(self, size: Tuple[int, int] = (1, 1), spacing: Tuple[float, float] = (1, 1)) -> 'Insert':
        """
        Place block reference in a grid layout, grid `size` defines the row- and column count,
        `spacing` defines the distance between two block references.

        Args:
            size: grid size as ``(row_count, column_count)`` tuple
            spacing: distance between placing as ``(row_spacing, column_spacing)`` tuple

        """
        if len(size) != 2:
            raise DXFValueError("Parameter size has to be a (row_count, column_count)-tuple.")
        if len(spacing) != 2:
            raise DXFValueError("Parameter spacing has to be a (row_spacing, column_spacing)-tuple.")
        self.dxf.row_count = size[0]
        self.dxf.column_count = size[1]
        self.dxf.row_spacing = spacing[0]
        self.dxf.column_spacing = spacing[1]
        return self
Exemple #5
0
 def _add(self, tags: Tags) -> None:
     tags = Tags(tags)
     if len(tags):
         appid = tags[0].value
         if appid in self.data:
             logger.info(f"Duplicate XDATA appid {appid} in one entity")
         if has_valid_xdata_group_codes(tags):
             self.data[appid] = tags
         else:
             raise DXFValueError(
                 f"found invalid XDATA group code in {tags}")
Exemple #6
0
    def _set_gradient(self, gradient_data: 'GradientData') -> None:
        gradient_data.name = gradient_data.name.upper()
        if gradient_data.name not in const.GRADIENT_TYPES:
            raise DXFValueError('Invalid gradient type name: %s' % gradient_data.name)

        self._remove_pattern_data()
        self._remove_gradient_data()
        self.dxf.solid_fill = 1
        self.dxf.pattern_name = 'SOLID'
        self.dxf.pattern_type = const.HATCH_TYPE_PREDEFINED
        self.AcDbHatch.extend(gradient_data.dxftags())
Exemple #7
0
    def set_open_rational(self, control_points: Sequence['Vertex'], weights: Sequence[float], degree: int = 3) -> None:
        """
        Open rational B-spline with uniform knot vector, start and end at your first and last control points, and has
        additional control possibilities by weighting each control point.

        """
        self.set_open_uniform(control_points, degree=degree)
        self.dxf.flags = self.dxf.flags | self.RATIONAL
        if len(weights) != len(control_points):
            raise DXFValueError('Control point count must be equal to weights count.')
        self.weights = weights
Exemple #8
0
    def replace(self, tag: str, value: str) -> None:
        """ Replaces the value of the first custom property `tag` by a new `value`.
        """
        properties = self.properties
        for index in range(len(properties)):
            name = properties[index][0]
            if name == tag:
                properties[index] = (name, value)
                return

        raise DXFValueError("Tag '%s' does not exist" % tag)
Exemple #9
0
    def acquire_arrow(self, name: str):
        """
        For standard AutoCAD and ezdxf arrows create block definitions if required, otherwise check if block `name`
        exist. (internal API)

        """
        from ezdxf.render.arrows import ARROWS
        if ARROWS.is_acad_arrow(name) or ARROWS.is_ezdxf_arrow(name):
            ARROWS.create_block(self.blocks, name)
        elif name not in self.blocks:
            raise DXFValueError(f'Arrow block "{name}" does not exist.')
Exemple #10
0
 def set_seed_points(self, points: Sequence[Tuple[float, float]]) -> None:
     if len(points) < 1:
         raise DXFValueError("Param points should be a collection of 2D points and requires at least one point.")
     hatch_tags = self.AcDbHatch
     first_seed_point_index = self._get_seed_point_index(hatch_tags)
     existing_seed_points = hatch_tags.collect_consecutive_tags([10],
                                                                start=first_seed_point_index)  # don't rely on 'Number of seed points'
     new_seed_points = [DXFVertex(10, (point[0], point[1])) for point in points]  # only use x and y coordinate,
     self.dxf.n_seed_points = len(new_seed_points)  # set new count of seed points
     # replace existing seed points
     hatch_tags[first_seed_point_index: first_seed_point_index + len(existing_seed_points)] = new_seed_points
Exemple #11
0
    def new(self, name: str, dxfattribs: dict = None) -> 'Layout':
        """
        Create a new Layout.

        Args:
            name (str): layout name as shown in tab
            dxfattribs (dict): DXF attributes for the ``LAYOUT`` entity

        """
        if not is_valid_name(name):
            raise DXFValueError('name contains invalid characters')

        if dxfattribs is None:
            dxfattribs = {}

        if name in self._layouts:
            raise DXFValueError('Layout "{}" already exists'.format(name))

        def create_dxf_layout_entity() -> str:
            dxfattribs['name'] = name
            dxfattribs['owner'] = self._dxf_layout_management_table.dxf.handle
            dxfattribs.setdefault('taborder', len(self._layouts) + 1)
            dxfattribs['block_record'] = block_record_handle
            entity = self.drawing.objects.create_new_dxf_entity(
                'LAYOUT', dxfattribs)
            return entity.dxf.handle

        block_layout = self.drawing.blocks.new_layout_block()
        block_record_handle = block_layout.block_record_handle
        block_record = block_layout.block_record
        layout_handle = create_dxf_layout_entity()
        block_record.dxf.layout = layout_handle

        # create valid layout entity
        layout = Layout(self.drawing, layout_handle)

        # add layout to management tables
        self._dxf_layout_management_table[name] = layout_handle
        self._layouts[name] = layout

        return layout
Exemple #12
0
    def get(self, appid: str) -> Tags:
        """Returns the DXF tags as :class:`~ezdxf.lldxf.tags.Tags` list
        stored by `appid`.

        Raises:
             DXFValueError: no data for `appid` exist

        """
        if appid in self.data:
            return self.data[appid]
        else:
            raise DXFValueError(appid)
Exemple #13
0
 def get_extension_dict(self, create=True):
     block_record = self.block_record
     try:
         xdict = block_record.get_extension_dict()
     except (DXFValueError, DXFKeyError):
         # DXFValueError: block_record has no extension dict
         # DXFKeyError: block_record has an extension dict handle, but extension dict does not exist
         if create:
             xdict = block_record.new_extension_dict()
         else:
             raise DXFValueError('Extension dictionary do not exist.')
     return xdict
Exemple #14
0
def set_matrix(subclass, code, data):
    values = list(data)
    if len(values) != 16:
        raise DXFValueError("Transformation matrix requires 16 values.")

    try:
        insert_pos = subclass.tag_index(code)
    except DXFValueError:
        insert_pos = len(subclass)
    subclass.remove_tags((code, ))
    tags = [DXFTag(code, value) for value in values]
    subclass[insert_pos:insert_pos] = tags
Exemple #15
0
    def set_data(self, entities: Iterable['DXFGraphic']) -> None:
        """  Set `entities` as new group content, entities should be an iterable :class:`GraphicEntity` or
        inherited (LINE, CIRCLE, ...). Raises :class:`DXFValueError` if not all entities be on the same layout
        (modelspace or any paperspace layout but not block)

        """
        entities = list(entities)  # for generators
        if not all_entities_on_same_layout(entities):
            raise DXFValueError(
                "All entities have to be on the same layout (modelspace or any paperspace layout but not block).")
        self.clear()
        self._data = entities
Exemple #16
0
 def delete_vertices(self, pos, count=1):
     db = self.entitydb
     prev_vertex = self.__getitem__(pos - 1).tags if pos > 0 else self.tags
     vertex = db[prev_vertex.link]
     while vertex.dxftype() == 'VERTEX':
         db.delete_handle(prev_vertex.link)  # remove from database
         prev_vertex.link = vertex.link  # remove vertex from list
         count -= 1
         if count == 0:
             return
         vertex = db[prev_vertex.link]
     raise DXFValueError("invalid count")
Exemple #17
0
 def remove(self, tag: str, all: bool = False) -> None:
     """ Remove first occurrence of 'tag', removes all occurrences if param all is True.
     """
     found_tag = False
     for item in self.properties:
         if item[0] == tag:
             self.properties.remove(item)
             found_tag = True
             if not all:
                 return
     if not found_tag:
         raise DXFValueError("Tag '%s' does not exist" % tag)
Exemple #18
0
 def check(value):
     value = cast_value(attrib_def.code, value)
     if not attrib_def.is_valid_value(value):
         if attrib_def.fixer:
             value = attrib_def.fixer(value)
             logger.debug(f'Fixed invalid attribute "{key}" in entity'
                          f' {str(self._entity)} to "{str(value)}".')
         else:
             raise DXFValueError(
                 f'Invalid value {str(value)} for attribute "{key}" in '
                 f'entity {str(self._entity)}.')
     return value
Exemple #19
0
 def remove(self, tag: str, all: bool = False) -> None:
     """ Removes the first occurrence of custom property `tag`, removes all occurrences if `all` is ``True``.
     Raises `:class:`DXFValueError` if `tag`  does not exist.
     """
     found_tag = False
     for item in self.properties:
         if item[0] == tag:
             self.properties.remove(item)
             found_tag = True
             if not all:
                 return
     if not found_tag:
         raise DXFValueError("Tag '%s' does not exist" % tag)
Exemple #20
0
    def rename(self, old_name: str, new_name: str) -> None:
        """ Rename a layout from `old_name` to `new_name`.
        Can not rename layout ``'Model'`` and the new name of a layout must not exist.

        Args:
            old_name: actual layout name
            new_name: new layout name

        Raises:
            DXFValueError: try to rename ``'Model'``
            DXFValueError: Layout `new_name` already exist.

        """
        if old_name == 'Model':
            raise DXFValueError('Can not rename model space.')
        if new_name in self._layouts:
            raise DXFValueError('Layout "{}" already exist.'.format(new_name))

        layout = self._layouts[old_name]
        layout.rename(new_name)
        del self._layouts[old_name]
        self._layouts[new_name] = layout
Exemple #21
0
 def set_vertices(self, vertices: Sequence[Sequence[float]], is_closed: bool = 1) -> None:
     new_vertices = []
     for vertex in vertices:
         if len(vertex) == 2:
             x, y = vertex
             bulge = 0
         elif len(vertex) == 3:
             x, y, bulge = vertex
         else:
             raise DXFValueError("Invalid vertex format, expected (x, y) or (x, y, bulge)")
         new_vertices.append((x, y, bulge))
     self.vertices = new_vertices
     self.is_closed = is_closed
Exemple #22
0
    def delete(self, group: Union[DXFGroup, str]) -> None:
        """ Delete `group`, `group` can be an object of type :class:`DXFGroup` or a group name as string. """
        if isinstance(group, str):  # delete group by name
            name = group
        elif group.dxftype() == 'GROUP':
            name = group.get_name()
        else:
            raise DXFTypeError(group.dxftype())

        if name in self:
            super().delete(name)
        else:
            raise DXFValueError("GROUP not in group table registered.")
Exemple #23
0
 def set_pos(self, p1, p2=None, align=None):
     if align is None:
         align = self.get_align()
     align = align.upper()
     self.set_align(align)
     self.set_dxf_attrib('insert', p1)
     if align in ('ALIGNED', 'FIT'):
         if p2 is None:
             raise DXFValueError("Alignment '{}' requires a second alignment point.".format(align))
     else:
         p2 = p1
     self.set_dxf_attrib('align_point', p2)
     return self
Exemple #24
0
def bspline_control_frame(fit_points: Iterable['Vertex'],
                          degree: int = 3,
                          method: str = 'distance',
                          power: float = .5):
    """
    Generates the control points for the `B-spline`_ control frame by `Curve Global Interpolation`_.
    Given are the fit points and the degree of the B-spline. The function provides 3 methods for generating the
    parameter vector t:

    =================== ============================================================
    Method              Description
    =================== ============================================================
    ``'uniform'``       creates a uniform t vector, from ``0`` to ``1`` evenly spaced; see `uniform`_ method
    ``'distance'``      creates a t vector with values proportional to the fit point distances, see `chord length`_ method
    ``'centripetal'``   creates a t vector with values proportional to the fit point distances ^ ``power``; see `centripetal`_ method
    =================== ============================================================

    Args:
        fit_points: fit points of B-spline, as list of :class:`Vector` compatible objects
        degree: degree of B-spline
        method: calculation method for parameter vector t
        power: power for centripetal method

    Returns:
        :class:`BSpline`

    """
    def create_t_vector():
        if method == 'uniform':
            return uniform_t_vector(fit_points)  # equally spaced 0 .. 1
        elif method == 'distance':
            return distance_t_vector(fit_points)
        elif method == 'centripetal':
            return centripetal_t_vector(fit_points, power=power)
        else:
            raise DXFValueError('Unknown method: {}'.format(method))

    fit_points = Vector.list(fit_points)
    count = len(fit_points)
    order = degree + 1
    if order > count:
        raise DXFValueError(
            'Need more fit points for degree {}'.format(degree))

    t_vector = list(create_t_vector())
    knots = list(control_frame_knots(count - 1, degree, t_vector))
    control_points = global_curve_interpolation(fit_points, degree, t_vector,
                                                knots)
    bspline = BSpline(control_points, order=order, knots=knots)
    bspline.t_array = t_vector
    return bspline
def required_knot_values(count: int, order: int) -> int:
    # just to show the connections
    # count = count of control points = n + 1
    # k = order of spline = degree + 1
    # 2 <= k <= n + 1
    # p = degree
    # order = p + 1
    k = order
    n = count - 1
    p = k - 1
    if not (2 <= k <= (n + 1)):
        raise DXFValueError('Invalid count/order combination')
    # n + p + 2 = count + order
    return n + p + 2
    def get_xdata(self, appid: str) -> Tags:
        """ Returns extended data for `appid`.

        Args:
            appid: application name as defined in the APPID table.

        Raises:
            DXFValueError: no extended data for `appid` found

        """
        if self.xdata:
            return Tags(self.xdata.get(appid)[1:])
        else:
            raise DXFValueError(appid)
    def get_app_data(self, appid: str) -> Tags:
        """ Returns application defined data for `appid`.

        Args:
            appid: application name as defined in the APPID table.

        Raises:
            DXFValueError: no data for `appid` found

        """
        if self.appdata:
            return self.appdata.get(appid)[1:-1]
        else:
            raise DXFValueError(appid)
Exemple #28
0
    def move_to_layout(self, entity, layout):
        """
        Move entity from block layout to another layout.

        Args:
            entity: DXF entity to move
            layout: any layout (model space, paper space, block)

        """
        if entity.dxf.handle in self._entity_space:
            self.unlink_entity(entity)
            layout.add_entity(entity)
        else:
            raise DXFValueError('Layout does not contain entity.')
    def delete(self, group: DXFGroup) -> None:
        """
        Delete GROUP by name or Group() object.

        """
        if isinstance(group, str):  # delete group by name
            super(GroupManager, self).delete(group)
        else:  # group should be a DXFEntity
            group_handle = group.dxf.handle
            for name, _group in self:
                if group_handle == _group.dxf.handle:
                    super(GroupManager, self).delete(name)
                    return
            raise DXFValueError("GROUP not in group table registered.")
Exemple #30
0
    def commit(self) -> None:
        """Store all changes to the underlying :class:`XData` instance.
        This call is not required if using the :meth:`entity` context manager.

        Raises:
            DXFValueError: invalid chars ``"\\n"`` or ``"\\r"`` in a string
            DXFTypeError: invalid data type

        """
        data = []
        for value in self._data:
            if isinstance(value, str):
                if len(value) > 255:  # XDATA limit for group code 1000
                    raise DXFValueError("string too long, max. 255 characters")
                if "\n" in value or "\r" in value:
                    raise DXFValueError(
                        "found invalid line break '\\n' or '\\r'")
            code = self.group_codes.get(type(value))
            if code:
                data.append(dxftag(code, value))
            else:
                raise DXFTypeError(f"invalid type: {type(value)}")
        self.xdata.set_xlist(self._appid, self._name, data)