Reading and plotting drawings#
papermodels.paper.pdf#
Read and write PDF annotations with pikepdf.
- papermodels.paper.pdf.load_pdf_annotations(pdf_path, show_skipped=False, show_unimplemented=False)[source]#
Returns a lists of pdf annotations keyed by page index.
- papermodels.paper.pdf.update_pdf_annotations(pdf_path, parsed_annotations, export_path, append_text=False)[source]#
Returns None. Creates a copy of the file at ‘pdf_path’ with all of annotations representing structural elements (collector and transfer elements, not loads or legend entries) having their text field updated with the assigned tag of the structural element.
- papermodels.paper.pdf.update_annotation_text_field(pike_annot, text, replace=False)[source]#
Returns a copy of the ‘pike_annot’ with the text field updated with ‘text’. If ‘replace’ is True then the text field is completely replaced with ‘text’. If not, then ‘text’ is appended on a new line to the existing ‘text’.
- papermodels.paper.pdf.compare_annotations(pm_annot, pike_annot, page_num, rotate)[source]#
Returns True if the pm_annot is nominally equal to the ‘pike_annot’ by converting the ‘pike_annot’ to the ‘pm_annot’ and seeing if they are equal. Will return True for duplicate annotations.
- Parameters:
pm_annot (Annotation)
pike_annot (Annotation)
page_num (int)
rotate (int)
- Return type:
- papermodels.paper.pdf.pike_annotation_to_pm_annotation(annot, annot_idx, page_idx, rotate=None, display_unimplemented_annots=False)[source]#
Returns either an Annotation object or None. None is returned if:
The annotation has a “parent” key
Has the word “ignore” in the text field
If that annotation is a type that cannot be read yet
The annotation does not have a Subj key
Note: Numerical data within pike annotation objects are of type Decimal
- Parameters:
- Return type:
Annotation | None
- papermodels.paper.pdf.get_dash_pattern(annot, content_stream=None)[source]#
Returns the dash array of ‘annot’ as a tuple of floats (e.g. (4.0, 4.0)) or None if the annotation is drawn with a solid line.
The border style dictionary (/BS) is the authoritative source. If the annotation does not have one, the dash operator (‘[…] phase d’) in the appearance ‘content_stream’ is used instead. PDF editors encode solid lines in several ways (no /BS, /S /S, an empty dash array, ‘[] 0 d’); all of these are normalized to None so that solid lines compare equal regardless of the software used to draw them.
- papermodels.paper.pdf.parse_content_stream(stream)[source]#
Parses data in the content stream into an ordered dictionary. Keys are operators. Values are operands.
Currently only parses non-path data reliably. Path data is not parsed separately so, in the output dict, repetitive operators are overwritten in the dict (e.g. multiple ‘l’ operators will only have one entry).
papermodels.paper.dxf#
Read DXF drawings into Annotations, treating each DXF layer as an annotation’s text.
- papermodels.paper.dxf.load_dxf_directory(directory_path, directory_page_idx=None)[source]#
Returns a list of Annotations representing the annotations in all of the .dxf files within the ‘directory_path’.
If ‘directory_page_idx’ is not None, then its value will be applied to the .page_idx attribute for all annotations in all files within the directory. Otherwise, a page idx will be generated based on the “glob order” of the files in the directory and applied to the annotations originating from that file.
- Parameters:
- Return type:
- papermodels.paper.dxf.load_dxf_annotations(dxf_path, page_idx=0, polygonize_layers=None)[source]#
Returns a list of Annotations read from the DXF file at ‘dxf_path’.
- Parameters:
- Return type:
- papermodels.paper.dxf.dxf_file_to_dxf_entities(dxf_path, page_idx=0, polygonize_layers=None)[source]#
Returns a lists of pdf annotations keyed by page index.
- Parameters:
dxf_path (Path | str) – Path-like object representing the path to the PDF file to open.
dxf_dir – If provided, a list of paths which to find DXF files comprising a single model. The order of the paths is important and will be used to create the order of spatial planes in the model, in ascending order (the first path will be the lowest plane in the model).
annotations_layer – if None, all entities will be treated as annotation entities
pages_layer – if None, will treat all entities in the modelspace as belonging to the same spatial plane. If provided, then entities existing within each page rectangle will be treated as belonging to the same plane. Each set of annotation entities within the page must also include an “origin” annotation. The origin must be in the same place for each “page”.
pages_layer_order – Optional[str], one of {“ltr”, “rtl”, “ttb”, “btt”} left-to-right, right-to-left, top-to-bottom, bottom-to-top Which will be used to order the pages in ascending order.
polygonize_layers (list[str] | None) – A list of layers if passed will polygonize the individual linestrings on these layers.
page_idx (int)
- Return type:
- papermodels.paper.dxf.dxf_entity_to_shapely(entity, page_idx, local_idx, polygonize_lines=False)[source]#
Converts the entity into an Annotation
- Parameters:
- Return type:
- papermodels.paper.dxf.dxf_entities_to_annotations(dxf_entities)[source]#
Returns a list of annotation for the dxf-entities
- papermodels.paper.dxf.parse_block_coordinates(entity)[source]#
Extract sequenced coordinates from the block.
- papermodels.paper.dxf.parse_line_coords(entity)[source]#
Returns a DXF LINE entity as a LineString snapped to a 1e-3 grid.
- Parameters:
entity (DXFGraphic)
- papermodels.paper.dxf.parse_polyline_coords(entity)[source]#
Returns a DXF polyline entity as a Polygon snapped to a 1e-3 grid.
- Parameters:
entity (DXFGraphic)
papermodels.paper.annotations#
Parse, tag, filter, scale and align Annotations.
These functions turn raw Annotation
records into the attribute dictionaries consumed by
from_parsed_annotations().
- papermodels.paper.annotations.annotations_to_shapely(annots, as_geometry_collection=False)[source]#
Returns a shapely geometry representing the geometry in ‘annot’
- Parameters:
annots (list[Annotation]) – a list of Annotation objects
as_geometry_collection – If True, the geometries in ‘annots’ will all be grouped together in a shapely.geometry.GeometryCollection
- Return type:
- papermodels.paper.annotations.annotation_to_shapely(annot)[source]#
Returns an shapely geometry created from the annotation type and vertices in ‘annot’.
- Parameters:
annot (Annotation)
- Return type:
- papermodels.paper.annotations.get_annotation_geometry_pairs(annots)[source]#
Returns a dict of annotation, shapely geometry pairs
- Parameters:
annots (list[Annotation])
- Return type:
dict[Annotation, Geometry]
- papermodels.paper.annotations.parsed_annotations_to_loading_geometry(parsed_annots)[source]#
Convert annotations representing loading areas into a list of LoadingArea
- Parameters:
parsed_annots (dict[Annotation, dict])
- Return type:
list[LoadingGeometry]
- papermodels.paper.annotations.parse_annotations(annots, legend, legend_identifier)[source]#
Returns a dictionary of annotations organized by their legend entry. If the annotation type is not in the ‘legend’, then it is excluded from the results.
- Parameters:
annots (list[Annotation])
legend (list[Annotation])
legend_identifier (str)
- Return type:
- papermodels.paper.annotations.is_region_markup(annot_attrs)[source]#
True for markup that describes where a joist array spans rather than a structural element: extent lines and joist containers. These carry no reaction type.
- papermodels.paper.annotations.is_joist_container(annot_attrs)[source]#
Returns True if the parsed annotation attributes describe a joist container markup.
- papermodels.paper.annotations.tag_parsed_annotations(parsed_annots)[source]#
Adds an identifying tag to the annotation based on the page number of the annotation and its identified type. Prioritizes manually named tags according to thsi format: “{ABBR}{PAGE_ID}.{INDEX}”. If an annotation is not already tagged accordingly then it will be auto-assigned an integer index after all tagged annotations have been accounted for.
All tags are guaranteed to be unique.
- Parameters:
parsed_annots (dict[Annotation, dict])
- Return type:
- papermodels.paper.annotations.parse_tag_components(tag)[source]#
Returns a tuple of the tag components: type abbrev., page_id, tag_idx
- papermodels.paper.annotations.assign_page_id_to_annotations(annots, page_containers, left_to_right=True)[source]#
Returns a list of Annotation representing ‘annots’ after they have been assigned to their page container in ‘page_containers’.
- Parameters:
annots (list[Annotation])
page_containers (list[Annotation])
left_to_right (bool)
- Return type:
- papermodels.paper.annotations.enumerate_page_annotations(page_annots, left_to_right=True)[source]#
Returns the annotations in ‘annots’ that correspond to page-demarcation polygons organized in a seqential fashion.
- papermodels.paper.annotations.sort_annotations_by_page_polygon(annots, page_geom_map)[source]#
Sorts each annotation into its own list[Annotation] coresponding to which page they are contained in.
- Parameters:
annots (list[Annotation])
- Return type:
- papermodels.paper.annotations.align_annotations_to_pages(annotations_by_page)[source]#
Returns a copy of ‘annotations_by_page’ but with all annotations aligned within their respective pages by their origin points. The distance between the page origin points and the page corner is set by the distance of the first origin on the first page.
- Parameters:
annotations_by_page (dict[Polygon, list[Annotation]])
- Return type:
- papermodels.paper.annotations.reset_annotations_to_origin(annots_on_page, page_origin_xy, origin_centroid_xy, global_offset)[source]#
Translates all of the annotations in ‘annots_on_page’ so that the origin annotation (contained within ‘annots_on_page’) is located at ‘xy_offset’ from the bottom-left corner.
- Parameters:
annots_on_page (list[Annotation])
page_origin_xy (Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | bytes | str | _NestedSequence[complex | bytes | str])
origin_centroid_xy (Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | bytes | str | _NestedSequence[complex | bytes | str])
global_offset (Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | bytes | str | _NestedSequence[complex | bytes | str])
- Return type:
- papermodels.paper.annotations.get_origin_offset(origin_annot, page_poly)[source]#
Returns the xy offset of the ‘origin_annot’ to the bottom-left corner of the ‘page_annot’.
- papermodels.paper.annotations.get_origin_centroid(origin_annot)[source]#
Returns the centroid of the ‘origin_annot’ as an xy tuple.
- papermodels.paper.annotations.get_page_bottom_left_corner(page_poly)[source]#
Returns the coordinate fo the bottom left hand corner of the ‘page_annot’ (a rectangle)
- papermodels.paper.annotations.get_page_geom_by_page_index(page_annots)[source]#
Returns a dictionary that organizes the ‘page_annots’ by their page id.
- papermodels.paper.annotations.parse_annot_kwargs(text_contents)[source]#
Returns a dictionary representing the kwargs that may be encoded into the text field of the annotation
- papermodels.paper.annotations.remove_windows_crlf(text_contents)[source]#
Normalizes Windows (CRLF) and classic Mac (CR) line endings to LF.
- papermodels.paper.annotations.filter_annotations(annots, properties)[source]#
Returns a list of annotations from ‘annots’ that have properties that match the keywords in ‘properties’. Note: The filtering process currently requires that both the keys AND values in ‘properties’ be hashable. ‘properties’ is a dictionary of annotation properties and their values, e.g.
{‘line_weight’: 3.0, ‘line_color’: (1, 0, 0)} or {‘text’: “Slab Outline”}
The returned annotations will only be annotations that match ALL of the properties described.
- Parameters:
annots (list[Annotation])
properties (dict)
- Return type:
- papermodels.paper.annotations.scale_annotations(annots, scale, paper_origin=None, round_precision=4)[source]#
Scale the annotations in ‘annots’. Each vertex in each annotation in ‘annots’ will be multiplied by ‘scale’. If ‘paper_origin’ is provided, then the annotation coordinates will have their origin reset to ‘paper_origin’. Note that ‘paper_origin’ is the unscaled coordinate space (i.e. in points) The purpose of setting ‘paper_origin’ if the annotation has a “datum” that is set somewhere in the file. Leave as None if there is no datum set.
- Parameters:
- Return type:
- papermodels.paper.annotations.parse_legend(legend_text, legend_identifier)[source]#
Returns a dict of key/value pairs extracted from teh legened annotation text
papermodels.paper.plot#
Matplotlib plotting of annotations and elements.
- papermodels.paper.plot.plot_elements(elements, figsize=(17, 11), dpi=100, plot_trib_areas=False, plot_extent_polygons=False, plot_subelement_tags=False, plot_elems_by_tag=None)[source]#
Plots the elements in matplotlib. Size and dpi can be adjusted to make the plot bigger/smaller. Size is in inches and dpi stands for “dots per inch”. For a biggish plot, values of size=12, dpi=200 gives good results.
Colors are based on the kind of element that is being plotted
- papermodels.paper.plot.get_element_plotting_attributes(element, is_subelement=False)[source]#
Returns a dict of plotting attributes for the element.
e.g. {
“is_poly”: True, “is_line”: False, “is_linear”: False, “is_subelement”: False, “tag”: str, “rank”: int, “xy”: np.array([[…], […]]), “anchor_point”: np.array([…, …]), “extent_polygon_xy”: np.array([[…], […]]) | None, “trib_area_xy”: np.array([[…], […]]) | None,
}
- papermodels.paper.plot.plot_annotations(annots, figsize=(17, 11), dpi=100, plot_tags=False, plot_annots_by_tag=None)[source]#
Plots that annotations, ‘annots’ in matplotlib. Size and dpi can be adjusted to make the plot bigger/smaller. Size is in inches and dpi stands for “dots per inch”. For a biggish plot, values of size=12, dpi=200 gives good results.