Skip to content

Commit

Permalink
more refactoring and fixed component building.
Browse files Browse the repository at this point in the history
  • Loading branch information
Krande committed Oct 3, 2024
1 parent a6da96e commit 54ff141
Show file tree
Hide file tree
Showing 39 changed files with 1,108 additions and 659 deletions.
22 changes: 4 additions & 18 deletions examples/procedure_example/components/create_floor.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,24 @@
import pathlib

import typer

import ada
from ada.comms.fb_model_gen import FileTypeDC
from ada.comms.procedures import procedure_decorator
from ada.config import Config
from ada.procedural_modelling.components_base import component_decorator, app

app = typer.Typer()

@procedure_decorator(app, export_file_type=FileTypeDC.IFC, export_file_var="output_file")
@component_decorator(export_file_type=FileTypeDC.IFC)
def main(
name: str = 'floor1',
origin: tuple[float, float, float] = (0, 0, 0),
width: float = 40,
length: float = 20,
thickness: float = 0.01,
output_file: pathlib.Path = None
) -> pathlib.Path:

temp_dir = Config().websockets_server_temp_dir
this_file_name = pathlib.Path(__file__).stem
output_dir = temp_dir / "components" / this_file_name
) -> None:

p = ada.Part(name) / ada.Plate("pl1", [(0, 0), (width, 0), (width, length), (0, length)], thickness, origin=origin)
# The assembly level is to be discarded. Only the part is relevant for merging into another IFC file
a = ada.Assembly("TempAssembly") / p
output_dir.mkdir(parents=True, exist_ok=True)
new_file = output_dir / f"{this_file_name}.ifc"
if new_file.exists():
new_file.unlink()
a.to_ifc(new_file)

return new_file
a.to_ifc(output_file)


if __name__ == "__main__":
Expand Down
16 changes: 5 additions & 11 deletions examples/procedure_example/procedures/add_stiffeners.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import pathlib

import numpy as np
import typer

import ada
from ada.comms.fb_model_gen import FileTypeDC
from ada.comms.procedures import procedure_decorator
from ada.procedural_modelling.procedures_base import procedure_decorator, app

app = typer.Typer()
THIS_FILE = pathlib.Path(__file__).resolve().absolute()


Expand Down Expand Up @@ -46,20 +44,16 @@ def add_stiffeners(pl: ada.Plate) -> list[ada.Beam]:
return stiffeners


@procedure_decorator(app, input_file_var="ifc_file", input_file_type=FileTypeDC.IFC, export_file_type=FileTypeDC.IFC)
def main(ifc_file: pathlib.Path = None, output_file: pathlib.Path = None) -> pathlib.Path:
@procedure_decorator(input_file_type=FileTypeDC.IFC, export_file_type=FileTypeDC.IFC)
def main(input_file: pathlib.Path = None, output_file: pathlib.Path = None) -> None:
"""A procedure to add stiffeners to all plates in the IFC file"""

a = ada.from_ifc(ifc_file)
a = ada.from_ifc(input_file)
for pl in a.get_all_physical_objects(by_type=ada.Plate):
new_stiffeners = add_stiffeners(pl)
pl.parent / new_stiffeners

modified_ifc_file = (ifc_file.parent / "procedural" / ifc_file.stem / THIS_FILE.stem).with_suffix(".ifc")
modified_ifc_file.parent.mkdir(parents=True, exist_ok=True)
a.to_ifc(modified_ifc_file)

return modified_ifc_file
a.to_ifc(output_file)


if __name__ == "__main__":
Expand Down
4 changes: 3 additions & 1 deletion src/ada/comms/fb_deserializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ def deserialize_procedure(fb_obj) -> ProcedureDC | None:
input_file_var=fb_obj.InputFileVar().decode('utf-8') if fb_obj.InputFileVar() is not None else None,
input_file_type=FileTypeDC(fb_obj.InputFileType()),
export_file_type=FileTypeDC(fb_obj.ExportFileType()),
state=ProcedureStateDC(fb_obj.State())
export_file_var=fb_obj.ExportFileVar().decode('utf-8') if fb_obj.ExportFileVar() is not None else None,
state=ProcedureStateDC(fb_obj.State()),
is_component=fb_obj.IsComponent()
)


Expand Down
2 changes: 2 additions & 0 deletions src/ada/comms/fb_model_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,9 @@ class ProcedureDC:
input_file_var: str = ""
input_file_type: Optional[FileTypeDC] = None
export_file_type: Optional[FileTypeDC] = None
export_file_var: str = ""
state: Optional[ProcedureStateDC] = None
is_component: bool = None

@dataclass
class ValueDC:
Expand Down
7 changes: 7 additions & 0 deletions src/ada/comms/fb_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@ def serialize_procedure(builder: flatbuffers.Builder, obj: Optional[ProcedureDC]
input_file_var_str = None
if obj.input_file_var is not None:
input_file_var_str = builder.CreateString(str(obj.input_file_var))
export_file_var_str = None
if obj.export_file_var is not None:
export_file_var_str = builder.CreateString(str(obj.export_file_var))

Procedure.Start(builder)
if name_str is not None:
Expand All @@ -225,8 +228,12 @@ def serialize_procedure(builder: flatbuffers.Builder, obj: Optional[ProcedureDC]
Procedure.AddInputFileType(builder, obj.input_file_type.value)
if obj.export_file_type is not None:
Procedure.AddExportFileType(builder, obj.export_file_type.value)
if export_file_var_str is not None:
Procedure.AddExportFileVar(builder, export_file_var_str)
if obj.state is not None:
Procedure.AddState(builder, obj.state.value)
if obj.is_component is not None:
Procedure.AddIsComponent(builder, obj.is_component)
return Procedure.End(builder)


Expand Down
4 changes: 2 additions & 2 deletions src/ada/comms/msg_handling/default_on_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def default_on_message(server: WebSocketAsyncServer, client: ConnectedClient, me
try:
message = deserialize_root_message(message_data)
if message.command_type == CommandTypeDC.UPDATE_SCENE:
update_scene(server, client, message)
update_scene(server, client, message.scene.current_file)
elif message.command_type == CommandTypeDC.UPDATE_SERVER:
update_server(server, client, message.server.new_file_object)
elif message.command_type == CommandTypeDC.MESH_INFO_CALLBACK:
Expand All @@ -34,7 +34,7 @@ def default_on_message(server: WebSocketAsyncServer, client: ConnectedClient, me
elif message.command_type == CommandTypeDC.LIST_FILE_OBJECTS:
list_file_objects(server, client, message)
elif message.command_type == CommandTypeDC.VIEW_FILE_OBJECT:
view_file_object(server, client, message)
view_file_object(server, client, message.server.get_file_object_by_name)
else:
logger.error(f"Unknown command type: {message.command_type}")
on_error_reply(server, client, error_message=f"Unknown command type: {message.command_type}")
Expand Down
60 changes: 43 additions & 17 deletions src/ada/comms/msg_handling/run_procedure.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
from __future__ import annotations

import pathlib
import random
import uuid
from typing import TYPE_CHECKING

from ada.comms.fb_model_gen import FileObjectDC, MessageDC, ParameterDC, ParameterTypeDC, ProcedureStartDC
from ada.comms.fb_model_gen import FileObjectDC, MessageDC, ParameterTypeDC, ProcedureStartDC, FileTypeDC, ValueDC, \
ParameterDC, FilePurposeDC
from ada.comms.msg_handling.update_scene import update_scene
from ada.comms.msg_handling.update_server import update_server
from ada.comms.procedures import Procedure
from ada.comms.msg_handling.view_file_object import view_file_object
from ada.comms.wsock.Value import Value
from ada.procedural_modelling.procedure_model import Procedure
from ada.config import logger
from tempfile import NamedTemporaryFile

if TYPE_CHECKING:
from ada.comms.wsock_server import ConnectedClient, WebSocketAsyncServer
Expand All @@ -18,37 +25,54 @@ def run_procedure(server: WebSocketAsyncServer, client: ConnectedClient, message

procedure: Procedure = server.procedure_store.get(start_procedure.procedure_name)
params = {p.name: p for p in start_procedure.parameters}

if "output_file" not in params.keys():
# add output_file if not exist
output_dir = procedure.get_output_dir()
if procedure.export_file_type == FileTypeDC.IFC:
suffix = ".ifc"
elif procedure.export_file_type == FileTypeDC.GLB:
suffix = ".glb"
else:
raise NotImplementedError(f"Export file type {procedure.export_file_type} not implemented")

# output_dir.mkdir(parents=True, exist_ok=True)
params["output_file"] = ParameterDC(
name="output_file",
type=ParameterTypeDC.STRING,
value=ValueDC(string_value=(output_dir / f"{procedure.name}-{random.randint(10000,20000)}{suffix}").as_posix()))

procedure(**params)

logger.info(f"Procedure {procedure.name} ran successfully")

update_server_on_successful_procedure_run(server, procedure, client, message, start_procedure)
update_server_on_successful_procedure_run(server, procedure, client, message, params)


def update_server_on_successful_procedure_run(
server: WebSocketAsyncServer, procedure: Procedure, client: ConnectedClient, message: MessageDC, start_procedure: ProcedureStartDC
server: WebSocketAsyncServer, procedure: Procedure, client: ConnectedClient, message: MessageDC,
parameters: dict[str, ParameterDC]
) -> None:
params = [p for p in start_procedure.parameters if p.name == procedure.input_file_var]
if len(params) == 0:

if procedure.is_component:
# it's a component procedure
input_file_path = None
output_dir = procedure.get_component_output_dir()
if procedure.export_file_type
output_file = output_dir /
purpose = FilePurposeDC.DESIGN
else:
# it's a modification procedure on an existing file
param = params[0]
if param.type == ParameterTypeDC.STRING:
input_file_path = pathlib.Path(param.value.string_value)
elif param.type == ParameterTypeDC.UNKNOWN and param.value.string_value:
input_file_path = pathlib.Path(param.value.string_value)
else:
input_file = parameters.get("input_file")
if input_file is None:
raise ValueError("No input file provided for procedure?")
input_file_value = input_file.value.string_value
if input_file_value is None:
raise NotImplementedError("Only string input file paths are supported for now")

input_file_path = pathlib.Path(input_file_value)
server_file_object = server.scene.get_file_object(input_file_path.stem)
output_file = procedure.get_procedure_output(input_file_path.stem)
if server_file_object is None:
raise ValueError(f"Input file {input_file_path.stem} not found on server")
purpose = server_file_object.purpose

output_file = pathlib.Path(parameters.get("output_file").value.string_value)
new_file_object = FileObjectDC(
name=output_file.name,
filepath=output_file,
Expand All @@ -57,5 +81,7 @@ def update_server_on_successful_procedure_run(
is_procedure_output=True,
procedure_parent=message.procedure_store.start_procedure,
)

update_server(server, client, new_file_object)
view_file_object(server, client, new_file_object.name)
logger.info(f"Completed Procedure '{procedure.name}' and added the File Object '{output_file}' to the server")
3 changes: 1 addition & 2 deletions src/ada/comms/msg_handling/update_scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@
from ada.comms.wsock_server import ConnectedClient, WebSocketAsyncServer


def update_scene(server: WebSocketAsyncServer, client: ConnectedClient, message: MessageDC) -> None:
def update_scene(server: WebSocketAsyncServer, client: ConnectedClient, glb_file_data: FileObjectDC) -> None:
logger.info(f"Received message from {client} to update scene")
glb_file_data = message.scene.current_file
tmp_dir = (
pathlib.Path("temp") if Config().websockets_server_temp_dir is None else Config().websockets_server_temp_dir
)
Expand Down
7 changes: 4 additions & 3 deletions src/ada/comms/msg_handling/view_file_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@
from ada.comms.wsock_server import ConnectedClient, WebSocketAsyncServer


def view_file_object(server: WebSocketAsyncServer, client: ConnectedClient, message: MessageDC) -> None:
def view_file_object(server: WebSocketAsyncServer, client: ConnectedClient, file_object_name: str) -> None:
logger.info(f"Received message from {client} to get file object")
file_object_name = message.server.get_file_object_by_name
result = server.scene.get_file_object(file_object_name)
if result is None:
raise ServerError(f"File object {file_object_name} not found")
Expand All @@ -43,11 +42,13 @@ def view_file_object(server: WebSocketAsyncServer, client: ConnectedClient, mess
msg = MessageDC(
instance_id=server.instance_id,
command_type=CommandTypeDC.SERVER_REPLY,
server_reply=ServerReplyDC(reply_to=message.command_type, file_object=file_object),
server_reply=ServerReplyDC(reply_to=CommandTypeDC.VIEW_FILE_OBJECT, file_object=file_object),
scene=SceneDC(current_file=file_object),
target_id=client.instance_id,
target_group=client.group_type,
)

fb_message = serialize_message(msg)
asyncio.run(client.websocket.send(fb_message))

server.scene.mesh_meta = scene.metadata
Loading

0 comments on commit 54ff141

Please sign in to comment.