Pushpak21 commited on
Commit
7f424c1
·
verified ·
1 Parent(s): b046e84

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. app.py +76 -80
  2. index.html +78 -54
  3. requirements.txt +0 -1
app.py CHANGED
@@ -1,94 +1,90 @@
 
1
  from fastapi import FastAPI, UploadFile, File
2
- from fastapi.responses import FileResponse, JSONResponse
3
- from fastapi.staticfiles import StaticFiles
4
- import json
5
 
6
  app = FastAPI()
7
- app.mount("/", StaticFiles(directory="static", html=True), name="static")
8
 
9
- def parse_dcm_assembly(uploaded_file):
10
- lines = uploaded_file.file.read().decode("utf-8").splitlines()
 
 
 
11
 
12
- geometry = {}
13
- parts = []
14
- constraints = {}
15
 
16
- temp_geom = {}
17
- temp_part = {}
18
- temp_constraint = {}
19
- current_class = None
20
 
21
- plane_label_map = {}
22
- plane_point_map = {}
 
23
 
24
  for line in lines:
25
- line = line.strip()
26
  if line.startswith("CLASS"):
27
- parts_line = line.split()
28
- current_class = parts_line[1]
29
- current_id = int(parts_line[2])
30
- if current_class == "PLANE":
31
- temp_geom = {"tag": current_id}
32
- elif current_class == "WORK_PLANE":
33
- temp_geom["tag"] = current_id
34
- elif current_class == "SET":
35
- temp_part = {"member_tags": []}
36
- elif current_class == "CONSTRAINT":
37
- temp_constraint = {}
38
- elif current_class == "PLANE":
39
- if line.startswith("FBASE_POINT"):
40
- temp_geom["base_point"] = tuple(map(float, line.split()[1:]))
41
- elif line.startswith("FNORMAL"):
42
- temp_geom["normal"] = tuple(map(float, line.split()[1:]))
43
- elif line.startswith("FIN_SET"):
44
- plane_point_map[temp_geom["tag"]] = temp_geom
45
- elif current_class == "WORK_PLANE":
46
- if line.startswith("FMY_PLANE TAG"):
47
- temp_geom["plane_tag"] = int(line.split()[-1])
48
- elif line.startswith("DCM3_TEXT_LABEL"):
49
- temp_geom["label"] = line.split(" ", 1)[1].strip()
50
- elif line == "#":
51
- tag = temp_geom.get("plane_tag")
52
- if tag is not None:
53
- plane_label_map[tag] = temp_geom.get("label", "")
54
- elif current_class == "SET":
55
- if line.startswith("DCM3_TEXT_LABEL"):
56
- temp_part["name"] = line.split(" ", 1)[1].strip()
57
- elif line.startswith("FMEMBER TAGS"):
58
- tags = list(map(int, line.split()[2:]))
59
- temp_part["member_tags"].extend(tags)
60
- elif line == "#":
61
- parts.append(temp_part)
62
- elif current_class == "CONSTRAINT":
63
- if line.startswith("FEND_1 TAG"):
64
- temp_constraint["from"] = int(line.split()[-1])
65
- elif line.startswith("FEND_2 TAG"):
66
- temp_constraint["to"] = int(line.split()[-1])
67
- elif line.startswith("DCM3_TEXT_LABEL"):
68
- temp_constraint["label"] = line.split(" ", 1)[1].strip()
69
- elif line == "#":
70
- if "from" in temp_constraint and "to" in temp_constraint:
71
- constraints[(temp_constraint["from"], temp_constraint["to"])] = temp_constraint["label"]
72
 
73
- final_geometry = {}
74
- for tag, data in plane_point_map.items():
75
- final_geometry[tag] = {
76
- "base_point": data["base_point"],
77
- "normal": data["normal"],
78
- "label": plane_label_map.get(tag, "")
79
- }
 
 
 
 
80
 
81
- constraint_list = [{"from": f, "to": t, "label": lbl} for (f, t), lbl in constraints.items()]
 
 
 
 
 
 
 
 
 
82
 
83
- return {
84
- "geometry": final_geometry,
85
- "parts": parts,
86
- "constraints": constraint_list
87
- }
88
 
89
- @app.post("/upload")
90
- async def upload_file(file: UploadFile = File(...)):
91
- data = parse_dcm_assembly(file)
92
- with open("static/parsed_data.json", "w") as f:
93
- json.dump({"files": [("red", "blue", data)]}, f)
94
- return JSONResponse(content={"status": "ok"})
 
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 CHANGED
@@ -1,3 +1,4 @@
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
@@ -12,70 +13,93 @@
12
  </head>
13
  <body>
14
  <h1>DCM Assembly Visualizer</h1>
15
- <p>Select a file using the backend (upload via /upload endpoint) and refresh this page.</p>
16
- <div id="plot">Loading 3D viewer...</div>
 
 
17
 
18
  <script>
19
- async function drawFromServer() {
20
- try {
21
- const res = await fetch("/parsed_data.json");
22
- const payload = await res.json();
23
- console.log("Loaded data:", payload);
24
 
25
- let allTraces = [];
 
 
 
26
 
27
- for (const [color, normalColor, data] of payload.files) {
28
- for (const [tag, g] of Object.entries(data.geometry)) {
29
- const [x, y, z] = g.base_point;
30
- const [nx, ny, nz] = g.normal;
31
 
32
- allTraces.push({
33
- type: 'scatter3d',
34
- mode: 'markers+text',
35
- x: [x], y: [y], z: [z],
36
- marker: { color: color, size: 5 },
37
- text: [g.label || tag],
38
- textposition: 'top center'
39
- });
40
 
41
- allTraces.push({
42
- type: 'scatter3d',
43
- mode: 'lines',
44
- x: [x, x + nx],
45
- y: [y, y + ny],
46
- z: [z, z + nz],
47
- line: { color: normalColor, width: 2 }
48
- });
49
- }
50
 
51
- for (const c of data.constraints) {
52
- const g1 = data.geometry[c.from];
53
- const g2 = data.geometry[c.to];
54
- if (g1 && g2) {
55
- const [x1, y1, z1] = g1.base_point;
56
- const [x2, y2, z2] = g2.base_point;
57
- allTraces.push({
58
- type: 'scatter3d',
59
- mode: 'lines',
60
- x: [x1, x2], y: [y1, y2], z: [z1, z2],
61
- line: { color: 'green', dash: 'dot', width: 2 }
62
- });
63
- }
64
- }
65
- }
 
 
 
 
66
 
67
- Plotly.newPlot('plot', allTraces, {
68
- margin: { t: 30 },
69
- scene: { aspectmode: 'data' },
70
- title: '3D Assembly Viewer'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  });
72
- } catch (e) {
73
- console.error("Failed to load or draw", e);
74
- document.getElementById("plot").innerText = "Failed to load data or draw. Check console.";
75
  }
76
- }
77
 
78
- drawFromServer();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  </script>
80
  </body>
81
- </html>
 
1
+
2
  <!DOCTYPE html>
3
  <html lang="en">
4
  <head>
 
13
  </head>
14
  <body>
15
  <h1>DCM Assembly Visualizer</h1>
16
+ <input type="file" id="file1" accept=".txt"> File A<br>
17
+ <input type="file" id="file2" accept=".txt"> File B<br><br>
18
+ <button onclick="uploadFiles()">Visualize</button>
19
+ <div id="plot"></div>
20
 
21
  <script>
22
+ async function uploadFiles() {
23
+ const file1 = document.getElementById("file1").files[0];
24
+ const file2 = document.getElementById("file2").files[0];
 
 
25
 
26
+ if (!file1 && !file2) {
27
+ alert("Please select at least one file.");
28
+ return;
29
+ }
30
 
31
+ const traces = [];
 
 
 
32
 
33
+ if (file1) {
34
+ const data1 = await sendFile(file1);
35
+ traces.push(...extractTraces(data1, 'File A', 'red', 'blue'));
36
+ }
 
 
 
 
37
 
38
+ if (file2) {
39
+ const data2 = await sendFile(file2);
40
+ traces.push(...extractTraces(data2, 'File B', 'purple', 'orange'));
41
+ }
 
 
 
 
 
42
 
43
+ Plotly.newPlot('plot', traces, {
44
+ margin: { t: 30 },
45
+ scene: { aspectmode: 'data' },
46
+ title: '3D Assembly Viewer'
47
+ });
48
+ }
49
+
50
+ async function sendFile(file) {
51
+ const formData = new FormData();
52
+ formData.append("file", file);
53
+ const res = await fetch("/parse", {
54
+ method: "POST",
55
+ body: formData
56
+ });
57
+ return await res.json();
58
+ }
59
+
60
+ function extractTraces(data, prefix, baseColor, normalColor) {
61
+ const traces = [];
62
 
63
+ for (const [tag, g] of Object.entries(data.geometry)) {
64
+ const [x, y, z] = g.base_point;
65
+ const [nx, ny, nz] = g.normal;
66
+
67
+ traces.push({
68
+ type: 'scatter3d',
69
+ mode: 'markers+text',
70
+ x: [x], y: [y], z: [z],
71
+ marker: { color: baseColor, size: 5 },
72
+ text: [`${prefix}: ${g.label || tag}`],
73
+ textposition: 'top center'
74
+ });
75
+
76
+ traces.push({
77
+ type: 'scatter3d',
78
+ mode: 'lines',
79
+ x: [x, x + nx],
80
+ y: [y, y + ny],
81
+ z: [z, z + nz],
82
+ line: { color: normalColor, width: 3 }
83
  });
 
 
 
84
  }
 
85
 
86
+ for (const c of data.constraints) {
87
+ const g1 = data.geometry[c.from];
88
+ const g2 = data.geometry[c.to];
89
+ if (g1 && g2) {
90
+ const [x1, y1, z1] = g1.base_point;
91
+ const [x2, y2, z2] = g2.base_point;
92
+ traces.push({
93
+ type: 'scatter3d',
94
+ mode: 'lines',
95
+ x: [x1, x2], y: [y1, y2], z: [z1, z2],
96
+ line: { color: 'green', dash: 'dot', width: 2 }
97
+ });
98
+ }
99
+ }
100
+
101
+ return traces;
102
+ }
103
  </script>
104
  </body>
105
+ </html>
requirements.txt CHANGED
@@ -2,4 +2,3 @@
2
  fastapi
3
  uvicorn
4
  python-multipart
5
- streamlit
 
2
  fastapi
3
  uvicorn
4
  python-multipart