Pushpak21 commited on
Commit
8161707
·
verified ·
1 Parent(s): 6f33aaf

Upload folder using huggingface_hub

Browse files
Files changed (4) hide show
  1. Dockerfile +18 -0
  2. app.py +90 -0
  3. index.html +101 -0
  4. requirements.txt +4 -0
Dockerfile ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # Dockerfile
3
+ FROM python:3.11
4
+
5
+ # Install backend dependencies
6
+ COPY requirements.txt /app/requirements.txt
7
+ WORKDIR /app
8
+ RUN pip install -r requirements.txt
9
+
10
+ # Copy backend and frontend
11
+ COPY app.py /app/app.py
12
+ COPY index.html /app/index.html
13
+
14
+ # Add CORS and serve index.html statically
15
+ RUN mkdir -p /app/static
16
+
17
+ # Run both backend (FastAPI) and static file server
18
+ CMD uvicorn app:app --host 0.0.0.0 --port 7860
app.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from fastapi import FastAPI, UploadFile, File
3
+ from fastapi.responses import JSONResponse, FileResponse
4
+ from fastapi.middleware.cors import CORSMiddleware
5
+ import os
6
+
7
+ app = FastAPI()
8
+
9
+ app.add_middleware(
10
+ CORSMiddleware,
11
+ allow_origins=["*"], allow_credentials=True,
12
+ allow_methods=["*"], allow_headers=["*"],
13
+ )
14
+
15
+ @app.get("/")
16
+ def serve_frontend():
17
+ return FileResponse("index.html")
18
+
19
+ @app.post("/parse")
20
+ async def parse_file(file: UploadFile = File(...)):
21
+ content = await file.read()
22
+ return JSONResponse(content=parse_dcm_assembly(content))
23
+
24
+ def parse_dcm_assembly(file_bytes):
25
+ lines = file_bytes.decode("utf-8").splitlines()
26
+ blocks, current = [], []
27
+
28
+ for line in lines:
29
+ if line.startswith("CLASS"):
30
+ if current:
31
+ blocks.append(current)
32
+ current = []
33
+ current.append(line.strip())
34
+ if current: blocks.append(current)
35
+
36
+ parts, geometry, constraints = [], {}, []
37
+ plane_map, tag_to_plane, label_map = {}, {}, {}
38
+
39
+ for block in blocks:
40
+ head = block[0]
41
+ if "CLASS SET " in head:
42
+ part, members = {}, []
43
+ for line in block:
44
+ if "DCM3_TEXT_LABEL" in line:
45
+ part['name'] = line.split("DCM3_TEXT_LABEL", 1)[1].strip()
46
+ elif "FMEMBER TAGS" in line:
47
+ members = list(map(int, line.split()[2:]))
48
+ if 'name' in part:
49
+ part['member_tags'] = members
50
+ parts.append(part)
51
+
52
+ elif "CLASS PLANE " in head:
53
+ pid = int(head.split()[-1])
54
+ base, norm = None, None
55
+ for line in block:
56
+ if "FBASE_POINT" in line:
57
+ base = tuple(map(float, line.split()[1:]))
58
+ elif "FNORMAL" in line:
59
+ norm = tuple(map(float, line.split()[1:]))
60
+ if base and norm:
61
+ plane_map[pid] = {'base_point': base, 'normal': norm}
62
+
63
+ elif "CLASS WORK_PLANE " in head:
64
+ wid = int(head.split()[-1])
65
+ tag, label = None, None
66
+ for line in block:
67
+ if "FMY_PLANE TAG" in line:
68
+ tag = int(line.split()[-1])
69
+ elif "DCM3_TEXT_LABEL" in line:
70
+ label = line.split("DCM3_TEXT_LABEL", 1)[1].strip()
71
+ if tag:
72
+ tag_to_plane[wid] = tag
73
+ label_map[wid] = label
74
+
75
+ elif "CLASS CONSTRAINT " in head:
76
+ con = {}
77
+ for line in block:
78
+ if "FEND_1 TAG" in line:
79
+ con['from'] = int(line.split()[-1])
80
+ elif "FEND_2 TAG" in line:
81
+ con['to'] = int(line.split()[-1])
82
+ elif "DCM3_TEXT_LABEL" in line:
83
+ con['label'] = line.split("DCM3_TEXT_LABEL", 1)[1].strip()
84
+ if con: constraints.append(con)
85
+
86
+ for wid, pid in tag_to_plane.items():
87
+ if pid in plane_map:
88
+ geometry[wid] = {**plane_map[pid], 'label': label_map.get(wid)}
89
+
90
+ return { "parts": parts, "geometry": geometry, "constraints": constraints }
index.html ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ <!-- index.html -->
3
+ <!DOCTYPE html>
4
+ <html lang="en">
5
+ <head>
6
+ <meta charset="UTF-8" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
+ <title>DCM Assembly Visualizer</title>
9
+ <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
10
+ <style>
11
+ body { font-family: sans-serif; padding: 20px; }
12
+ #plot { width: 100%; height: 700px; }
13
+ </style>
14
+ </head>
15
+ <body>
16
+ <h1>DCM Assembly Visualizer</h1>
17
+ <input type="file" id="file1" accept=".txt"> File A<br>
18
+ <input type="file" id="file2" accept=".txt"> File B<br><br>
19
+ <button onclick="uploadFiles()">Visualize</button>
20
+ <div id="plot"></div>
21
+
22
+ <script>
23
+ async function uploadFiles() {
24
+ const file1 = document.getElementById("file1").files[0];
25
+ const file2 = document.getElementById("file2").files[0];
26
+
27
+ if (!file1 || !file2) {
28
+ alert("Please select two files.");
29
+ return;
30
+ }
31
+
32
+ const data1 = await sendFile(file1);
33
+ const data2 = await sendFile(file2);
34
+ draw(data1, data2);
35
+ }
36
+
37
+ async function sendFile(file) {
38
+ const formData = new FormData();
39
+ formData.append("file", file);
40
+ const res = await fetch("http://localhost:7860/parse", {
41
+ method: "POST",
42
+ body: formData
43
+ });
44
+ return await res.json();
45
+ }
46
+
47
+ function draw(data1, data2) {
48
+ const traces = [];
49
+
50
+ function addAssembly(data, colorBase, colorNormal, prefix) {
51
+ for (const [tag, g] of Object.entries(data.geometry)) {
52
+ const [x, y, z] = g.base_point;
53
+ const [nx, ny, nz] = g.normal;
54
+
55
+ traces.push({
56
+ type: 'scatter3d',
57
+ mode: 'markers+text',
58
+ x: [x], y: [y], z: [z],
59
+ marker: { color: colorBase, size: 5 },
60
+ text: [`${prefix} ${g.label || tag}`],
61
+ textposition: 'top center'
62
+ });
63
+
64
+ traces.push({
65
+ type: 'scatter3d',
66
+ mode: 'lines',
67
+ x: [x, x + nx],
68
+ y: [y, y + ny],
69
+ z: [z, z + nz],
70
+ line: { color: colorNormal, width: 3 }
71
+ });
72
+ }
73
+
74
+ for (const c of data.constraints) {
75
+ const g1 = data.geometry[c.from];
76
+ const g2 = data.geometry[c.to];
77
+ if (g1 && g2) {
78
+ const [x1, y1, z1] = g1.base_point;
79
+ const [x2, y2, z2] = g2.base_point;
80
+ traces.push({
81
+ type: 'scatter3d',
82
+ mode: 'lines',
83
+ x: [x1, x2], y: [y1, y2], z: [z1, z2],
84
+ line: { color: 'green', dash: 'dot', width: 2 }
85
+ });
86
+ }
87
+ }
88
+ }
89
+
90
+ addAssembly(data1, 'red', 'blue', 'File A');
91
+ addAssembly(data2, 'purple', 'orange', 'File B');
92
+
93
+ Plotly.newPlot('plot', traces, {
94
+ margin: { t: 30 },
95
+ scene: { aspectmode: 'data' },
96
+ title: '3D Assembly Viewer'
97
+ });
98
+ }
99
+ </script>
100
+ </body>
101
+ </html>
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+
2
+ fastapi
3
+ uvicorn
4
+ python-multipart