Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions src/papermodels/datatypes/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,16 +284,13 @@ def get_collector_extents(self, relative: bool = True) -> dict[str, tuple]:
self.trib_area,
extent_polygon=self.extent_polygon,
)
except (geom_ops.GeometryError, AssertionError, ValueError) as e:
print(
except (geom_ops.GeometryError, AssertionError, ValueError, TypeError):
support_intersections = (
f"{GeometryCollection(ordered_support_geoms).intersection(self.geometry).wkt=}"
)
print(f"{self.geometry.wkt=}")
# raise AssertionError(
# f"No intersection within joist extents: {self.tag=}"
# )
print(f"{self.tag=}")
raise e
geometry = (f"{self.geometry.wkt=}")
tag = (f"{self.tag=}")
raise geom_ops.GeometryError(f"Debug information:{tag=}\n{geometry=}\n{support_intersections=}")
tagged_extents = {}
for idx, extent in enumerate(extents):
support_geom = ordered_support_geoms[idx]
Expand Down Expand Up @@ -730,7 +727,6 @@ def _get_transfer_loads(self, precision: int):
transfer_type = intersection_above.other_reaction_type
source_member = intersection_above.other_tag
reaction_idx = intersection_above.other_index
# print(transfer_type, source_member, reaction_idx)
if reaction_idx is None:
raise ValueError(
"The .other_index attribute within the .intersections_above list"
Expand Down Expand Up @@ -1374,7 +1370,12 @@ def trim_cantilevers(element: Element, abs_tol: Optional[float] = 0.02):
start_point = cantilevers["A_intersection"]
if (cantilevers["B"] == 0.0) and (cantilevers["B"] != cantilevers["B_orig"]):
end_point = cantilevers["B_intersection"]
new_geometry = LineString([start_point, end_point]) # type: ignore
try:
new_geometry = LineString([start_point, end_point]) # type: ignore
except TypeError:
raise geom_ops.GeometryError(
f"{element=}"
)
new_element.geometry = new_geometry
intersection_checks = [
new_geometry.intersects(ib.other_geometry)
Expand Down
26 changes: 25 additions & 1 deletion src/papermodels/datatypes/geometry_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,11 @@ def remove_excess_correspondent_load_paths(self):
frame element transferring load to the supporting frame element. The correct load
path should be |FB0.1 -> FB0.2 -> column| instead of |FB0.1 -> column| with
|FB0.1 -> FB0.2 -> column| also.
4. A Polygon node, with "linear" reaction type, that is intersecting with LineString
elements that run perpendicular to it. This can occur if a beam is drawn to
transfer out a wall from above but that same beam has other beams framing into
it perpendicular. We do not want the wall to transfer out to these other beams
at the intersection points.

Modifications to the implementation of this function can adjust how load paths are
conceptually created. For example, to implement baloon framing, the second rule
Expand Down Expand Up @@ -381,10 +386,29 @@ def remove_excess_correspondent_load_paths(self):
if (
element.geometry.geom_type == "LineString"
and intersection_points_in_polygon_below

):
for edge in intersection_points_in_polygon_below:
inters_below_set = set(intersection_points_in_polygon_below)
for edge in inters_below_set:
self.remove_edge(*edge)

# Rule 4
if (
element.geometry.geom_type == "Polygon"
and element.reaction_type == "linear"
and "intersection" in edge_properties
):
center_line = geom.get_rectangle_centerline(
element.geometry
)
for idx, dep in enumerate(dependents):
dep_geom = self.nodes[dep]["element"].geometry
if dep_geom.geom_type == "LineString":
is_roughly_parallel = geom.check_2d_linestring_parallel(center_line, dep_geom, tol=0.01)
if not is_roughly_parallel:
self.remove_edge(element.tag, dep)


def add_intersection_indexes_below(self):
sorted_nodes = nx.topological_sort(self)
orphaned_nodes = self.orphaned_elements
Expand Down
5 changes: 5 additions & 0 deletions src/papermodels/datatypes/joist_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,11 @@ def generate_joist_geom(self, index: int):
intersecting_supports, grid_size=1e-3
)
ordered_intersections = geom_ops.order_nodes_positive(support_locs)
if len(ordered_intersections) < 2:
return None
raise geom_ops.GeometryError(
f"Joist prototype {self.element.tag} is not intersecting correctly."
)
support_a_loc, support_b_loc = (
ordered_intersections[0],
ordered_intersections[-1],
Expand Down
2 changes: 2 additions & 0 deletions src/papermodels/paper/annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ def parse_annotations(
annot_attrs["geometry"] = annot_geom
annot_attrs["page_label"] = annot.page
annot_attrs["tag"] = existing_annot_tag
if annot_geom is None:
raise ValueError(f"{annot=}")
for annot_key, annot_attr in annot_attributes.items():
annot_attrs[annot_key] = str_to_int(
annot_attr.split("<")[0]
Expand Down
45 changes: 35 additions & 10 deletions src/papermodels/paper/pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,25 @@ def pike_annotation_to_pm_annotation(
annot_type = str(annot["/Subj"])
else:
return None
if annot_type.lower() in ("polygon", "polyline", "circle", "ellipse"):
if annot_type.lower() in ("polygon", "polyline"):
vertices = tuple(annot.get("/Vertices", tuple()))
elif annot_type.lower() in ("circle", "ellipse"):
annot_type = "Polygon"
rect = tuple(annot.get("/Rect", tuple()))
x1, y1, x2, y2 = rect
h = (x1 + x2) / 2
k = (y1 + y2) / 2
a = (x2 - x1) / 2
b = (y2 - y1) / 2
n = 16
x_vertices = float(h) + float(a) * np.cos(np.linspace(0, 2*np.pi, n))
y_vertices = float(k) + float(b) * np.sin(np.linspace(0, 2*np.pi, n))
vertices = []
for idx, x_vertex in enumerate(x_vertices):
vertices.append(Decimal(x_vertex))
y_vertex = y_vertices[idx]
vertices.append(Decimal(y_vertex))

elif annot_type.lower() in (
"rectangle",
"square",
Expand Down Expand Up @@ -243,21 +260,29 @@ def parse_content_stream(stream: str) -> dict[str, list]:
operators will only have one entry).
"""
commands = {}
operand_with_operator = re.compile(r"[0-9.\s]+[a-zA-Z]+")
operators = re.compile(f"[a-zA-Z]+")
operands = re.compile(r"[\d.]+")
operand_with_operator = re.compile(r"([\d+\s*|\d+\.\d+\s*]*)([A-Za-z]{1,2})\s*")
operators_pattern = re.compile(r"[a-zA-Z]+")
operands_pattern = re.compile(r"[\d.]+")
floats_pattern = re.compile(r"^\d+\.\d+$")
integers_pattern = re.compile(r"^\d+$")

matches = operand_with_operator.findall(stream)
for match in matches:
operator = operators.findall(match)[0]
operand = operands.findall(match)
# operator = operators.findall(match)[0]
# operand = operands.findall(match)
operands, operator = match
numerical_operands = []
for element in operand:
if "." in element:
operands_matches = operands_pattern.findall(operands)
for element in operands_matches:
element = element.strip()
float_match = floats_pattern.search(element)
integer_match = integers_pattern.search(element)
if float_match is not None:
elem = Decimal(element)
else:
numerical_operands.append(elem)
elif integer_match is not None:
elem = int(element)
numerical_operands.append(elem)
numerical_operands.append(elem)
commands.update({operator: numerical_operands})
return commands

Expand Down
Loading