Reverse engineering di 9253000117a.prt.35: contenitore (offset dall'ultimo campo dell'intestazione, indice a catena), grammatica completa delle sezioni (id progressivi dei campi, tabella "dopo X viene Y", marcatori di chiusura), tabella dei double verificata sulla norma delle matrici, sezioni compresse e catalogo del contenuto. Parser Python in scripts/psb/. docs/history.md raccoglie stato, metodo e punti aperti per riprendere il lavoro. Co-Authored-By: Claude <noreply@anthropic.com>
32 KiB
Decodifica del .prt Creo: numeri, quote e geometria degli schizzi
Seguito di formato-prt-feature.md, che spiega come trovare le sezioni
del file e leggere l'albero delle feature (ordine, tipo, nome). Qui: come leggere i numeri
(quote, coordinate) e come ricostruire da quelli la forma di una feature.
Aggiornamento. La lettura campo per campo di tutte le sezioni, e la tabella completa dei numeri, sono in
formato-psb.md, che corregge la §1 di questo doc (vedi lì §9).
Stato, da leggere prima di fidarsi. Questo doc contiene tutto quello che è stato decodificato
e verificato, e dice per ogni cosa quanto è provata. Non basta ancora a determinare in modo
univoco com'è fatto un .prt: manca il posizionamento delle feature nello spazio e il
significato certo di alcuni codici (§7 elenca cosa manca, dove sta nel file, e come finire il
lavoro). Nessun codice del progetto lo usa: è reverse engineering fatto con script di prova.
Livelli di prova, come negli altri doc:
- Contro Creo (schermate del modello aperto):
9252000507.prt.11, feature Rivoluzione 1 (§5). Quote e coordinate dello schizzo coincidono con quelle mostrate da Creo. - Coerenza e plausibilità:
test.prt.1e le altre feature di9252000507.prt.11. I valori sono numeri "tondi" e coerenti fra sezioni diverse, ma nessuno li ha confrontati con Creo.
1. Come sono scritti i numeri reali
Nelle sezioni a marcatori (formato-asm-record.md §2) i double sono
scritti in forma compatta. Si distinguono per il primo byte, tag:
| Tag (hex) | Byte dopo il tag | Valore | Prova |
|---|---|---|---|
18 |
0 | 0.0 |
in ogni sezione |
0f |
0 | 1.0 |
diagonale delle matrici identità |
0e |
0 | 0.5 |
livello 1: la quota di Smusso 1 (D = 0.500) è il solo byte 0e |
10 |
0 | -1.0 |
ipotesi dal contesto |
2f |
2 | 40 b1 b2 00 00 00 00 00 |
livello 1 (12,5; 69,5; 100; 139) e 2 (8, 20, 25, 75) |
2e |
2 | 40 b1 b2 b2 b2 b2 b2 b2 (l'ultimo byte si ripete) |
livello 1: 2e 1b 33 = 6,8, il diametro della punta mostrato da Creo |
2d |
7 | 40 b1 .. b7 (precisione piena) |
livello 2: 2d 39 7f ff ff ff ff ff = 25,5 |
2a |
2 | 3f b1 b2 00... |
livello 2: 2a f4 00 = 1,25, il passo di M8x1.25 |
48 |
2 | c0 b1 b2 00... (negativo) |
livello 1 (−12,5; −69,5) |
47 / 46 |
2 / 7 | stessa famiglia di 48, con ripetizione / precisione piena |
non isolati |
e4-e7 |
0 | K − 3 zeri di seguito, K = byte − e0 (solo dentro le matrici, §6.1) |
livello 1 (matrici di 9239902104) |
ed, 32... |
8-9 | altri byte alti | non decodificato |
La regola, ricavata dai dati (non da una specifica): a ogni byte alto T del double
corrispondono tre tag consecutivi, e la base si sposta di 5 per ogni passo di T:
tag_zero(T) = 0x2f + 5 * (T - 0x40) per i positivi (negativi: 0x48 + 5 * (T - 0xc0))
tag_zero -> T, b1, b2 e 5 byte a zero (valori "tondi")
tag_zero - 1 -> T, b1, b2 e b2 ripetuto 5 volte (es. 6,8 = 40 1b 33 33 33 33 33 33)
tag_zero - 2 -> T e 7 byte pieni (precisione piena)
Verifica: T = 0x40 dà 2f, 2e, 2d; T = 0x3f dà 2a (1,25 con f4 00); T = 0xc0 dà
48. Funziona solo finché i tag non si sovrappongono: i byte alti 0x41-0x43 e 0xb8-0xbf
non li ho incontrati e non so se la regola regge (i tag di 0x45 collidono con quelli dei
negativi). Per i valori "non tondi" con ripetizione (come 6,8 o 3,4) serve il tag 2e: senza
quello si leggerebbe 6.7998.
Come si ricostruisce un valore a 3 byte: si prende il double big-endian 40 b1 b2 00... (per
2f) oppure c0 b1 b2 00... (per 48). Esempi verificati (struct.unpack('>d', ...)):
| Byte | Valore | Dove |
|---|---|---|
2f 59 00 |
100.0 |
quota |
2f 52 c0 |
75.0 |
quota |
2f 51 60 |
69.5 |
coordinata y dello schizzo di Rivoluzione 1 (= 139 / 2) |
2f 29 00 |
12.5 |
coordinata x (= 25 / 2) |
48 29 00 |
-12.5 |
idem, lato opposto all'asse |
48 51 60 |
-69.5 |
idem |
2f 61 60 |
139.0 |
quota (lunghezza) |
48 59 00 |
-100.0 |
estremo della linea d'asse |
Le unità non sono scritte nel record. Nei campioni sono millimetri, ma il file ha una sezione
UnitSystemDef (nel contenitore compresso, §1.2 di formato-prt-feature.md) che non ho letto:
l'unità va presa da lì prima di dare un numero come "mm".
2. Le quote: dim_array in BasFullData
Ogni quota (dimensione guida) di ogni feature e di ogni schizzo è un record della sezione
BasFullData, array dim_array. Campi, nell'ordine in cui compaiono:
\xe1 nome della quota (qui sempre nullo: il nome "d12" si calcola altrove)
\x08 tipo del record
<dim_type> 1 byte: classe della quota (tabella sotto)
<feat_id> intero (formato asm-record §2.1): la feature a cui appartiene
<attributi> \xf8 \x02 ... flag
\xe3 <valore> <valore_di_backup> \xe3 ... due numeri uguali: value e bck_value
\xe3 \x09 \x01 ... <tolleranza> ... blocco della tolleranza (nominal_value, bound...)
Per leggere solo valore e feature basta ancorarsi a \xe1 \x08 <dim_type> <feat_id> e leggere il
primo numero che segue (§1). Il primo record dell'array è scritto con i nomi di campo per esteso
(layout diverso: non l'ho agganciato con lo stesso pattern, quindi la prima quota dell'array può
mancare).
feat_id è lo stesso id di AllFeatur e dello storico (formato-prt-feature.md §2 e §5): è il
modo per attribuire la quota a "Foro 1" o a "Estrusione 2".
2.1 Le quote lette sui due campioni
test.prt.1 (id → feature come in formato-prt-feature.md §6):
| Feature | dim_type |
Valore | Interpretazione |
|---|---|---|---|
| Estrusione 1 (79) | 62 | 75 | profondità (ipotesi) |
| Estrusione 1 (79) | 4 | 100 | diametro del cerchio dello schizzo: nello schizzo il raggio è 50 (entity(circle), radius) |
| Foro 1 (100) | 4 | 19 | diametro (ipotesi) |
| Foro 1 (100) | 62 | 40 | profondità (ipotesi) |
| Arrotondamento 1 (125) | 3 | 3,5 | raggio (ipotesi) |
| Estrusione 2 (149) | 62 / 1 / 1 | 11 / 25 / 53 | profondità e due quote dello schizzo (ipotesi) |
| Smusso 1 (188) | 9 | 6 | distanza dello smusso (ipotesi) |
9252000507.prt.11:
| Feature | dim_type |
Valore | Interpretazione |
|---|---|---|---|
| Rivoluzione 1 (73) | 2 | 25 | diametro, confermato da Creo (Ø25 h7) |
| Rivoluzione 1 (73) | 1 | 139 | lunghezza, confermata da Creo |
| Estrusione 1 / taglio (118) | 62 / 14 / 5 / 20 | 4 / 45 / 8 / 3 | non verificate |
| Foro 1 (157) | 4 / 9 / 2 / 10 / 2 | 8 / 20 / 6,8 / 118 / 25 | confermate da Creo (§6.4): 8 = diametro nominale, 20 = profondità filetto, 118 = angolo punta, 25 = profondità foro |
9239902104.prt.1 (piastra con tre fori, §6.4.1):
| Feature | dim_type |
Valore | Interpretazione |
|---|---|---|---|
| Sketch 1 / Estrusione 1 (84) | 1 / 5 / 1 | 21 / 54 / 125 (+ 46) | quote del profilo a L (§3.2) |
| Estrusione 1 (84) | 62 | 6 | profondità, coerente con y = 0 ... 6 delle facce |
| Sketch 2 / Foro 1 (124 / 131) | 8 / 2 / 2 / 7 | 38 / 8 / 8 / 30 | quote dei 4 punti (§6.4.1) |
| Foro 1 (131) | 4 | 5,5 | diametro |
| Sketch 3 / Foro 2 (1095 / 1099) | 2 / 2 | 4 / 5 | distanze del punto dai bordi: l'origine (67, 6, -5) = 71 − 4 e 5 |
| Foro 2 (1099) | 4 | 5 | diametro |
| Foro 3 (1132) | 4 / 9 / 2 / 2 | 3 / 6 / 2,5 / 137,5 | diametro nominale M3, profondità filetto, punta, lunghezza (distanza fino all'estremo, §6.1) |
| Sketch 4 / Estrusione 2 (1903 / 1911) | 1 / 62 | 3,5 / 3 | quota dello schizzo e profondità |
| Arrotondamento 1 (2777) | 3 | 3 | raggio, confermato dallo storico |
Cosa è provato e cosa no. I valori 25 e 139 di Rivoluzione 1 sono confermati da Creo
(§5). Per tutte le altre righe il numero è decodificato in modo plausibile ma il significato
(profondità? diametro?) è dedotto dal codice dim_type, da cui non ho una tabella certa. I codici
visti: 1 e 2 quote lineari/diametrali di schizzo, 3 raggio, 4 diametro, 9 distanza
(smusso), 62 profondità/estensione, altri (5, 10, 14, 37) non interpretati. Per
distinguere con certezza serve un confronto riga per riga con un modello noto, o leggere il
nome della quota (d0, d1... del Creo).
La tolleranza (es. h7 di Ø25) sta nello stesso record, ma non l'ho decodificata: nel campo
tol_class/tol_table_index compaiono indici, non la stringa h7.
3. La geometria di uno schizzo: p_saved_result
Ogni schizzo (sezione) ha, dentro BasFullData, un blocco:
gsec_ptr ... name "Sezione 1" <- nome mostrato nel tree
gsec2d_ptr name "S2D0001"
segtab_ptr / dimtab_ptr / dim_ref <- segmenti, quote e a cosa si riferiscono
...
p_saved_result
entity(line) ... <- le linee dello schizzo con le coordinate
entity(circle) ... <- i cerchi (centro, raggio)
local_sys 4x3 <- sistema di coordinate dello schizzo
Le coordinate delle entità sono nel sistema dello schizzo, non assolute (§6).
Ogni entity(line) ha due estremi con tre coordinate ciascuno (x, y, z); con z sempre 0 nello
schizzo. Le coordinate sono numeri come in §1.
3.1 Esempio verificato: Sezione 1 di Rivoluzione 1
Decodificando i numeri del blocco entity(line) di 9252000507.prt.11 si ottengono quattro
linee chiuse e una linea d'asse:
| Linea | Da (x, y) |
A (x, y) |
|---|---|---|
| 1 | (0, 69,5) | (−12,5, 69,5) |
| 2 | (−12,5, 69,5) | (−12,5, −69,5) |
| 3 | (−12,5, −69,5) | (0, −69,5) |
| 4 | (0, −69,5) | (0, 69,5) |
| asse | (0, −100) | (0, 100) |
È il rettangolo di larghezza 12,5 (= raggio) e altezza 139, centrato in y sul piano di
riferimento, con il lato destro sull'asse x = 0, e una linea d'asse più lunga della figura.
Coincide con quello che Creo mostra nella vista dello schizzo (rettangolo di 139 di altezza,
quotato 25 come diametro rispetto all'asse tratteggiato, simmetrico rispetto a TOP).
Nota: nel file la quota 25 è un diametro (Ø25), anche se in geometria il lato è 12,5. Per
questo non si può dedurre la forma dalle sole quote: servono anche le linee.
3.2 Secondo esempio: il profilo a L di Estrusione 1 (9239902104.prt.1)
Le linee del profilo (entity(line), estremi (x, y) nel sistema dello schizzo, z = 0):
| Linea | Da | A |
|---|---|---|
| 1 | (71, 0) | (−54, 0) |
| 2 | (−54, 0) | (−54, 46) |
| 3 | (−54, 46) | (0, 46) |
| 4 | (0, 46) | (0, 21) |
| 5 | (0, 21) | (71, 21) |
| 6 | (71, 21) | (71, 0) |
più una linea d'asse. Le quote 125 (= 54 + 71), 54, 46 e 21 sono tutte spiegate dal profilo. Qui le
linee stanno in FeatDefs (record della feature, sezione S2D0006), non in BasFullData come in
§3: la posizione del blocco p_saved_result dipende dal tipo di feature.
4. Da schizzo + quote alla forma: la rivoluzione
Con le due cose sopra, Rivoluzione 1 è determinata così:
profilo (nel piano dello schizzo): x in [-12,5 ; 0], y in [-69,5 ; 69,5]
asse di rotazione: la linea x = 0 (la linea d'asse dello schizzo)
angolo: 360 (non decodificato, vedi §7)
risultato: cilindro Ø25 x 139, centrato sull'origine lungo y dello schizzo
Nell'albero di Creo il cilindro risulta con il fondo sul piano DTM1 e l'asse come A_1: la
posizione assoluta (quale piano contiene lo schizzo, come è orientato y) non è nello schizzo
ma nella definizione della feature (§7).
5. Verifica di Rivoluzione 1 contro Creo
9252000507.prt aperto in Creo (schermate del model tree e dello schizzo):
| Cosa | Creo | Letto dal file |
|---|---|---|
| Lunghezza dello schizzo | 139.000 | quota dim_type 1 = 139 |
| Diametro | Ø25 (h7) | quota dim_type 2 = 25 |
Rettangolo, simmetrico rispetto a TOP |
sì | y da −69,5 a 69,5 |
| Rettangolo a sinistra dell'asse | sì | x da −12,5 a 0 |
| Asse (linea di costruzione) | più lungo della figura | da y = −100 a 100 |
| Assi A_3, A_4, A_5, punto PNT0 | presenti nel tree | AllFeatur + storico (formato-prt-feature.md) |
6. Posizione nello spazio
6.1 Matrici 4×3
Piani di riferimento, assi, sistemi di coordinate, schizzi e feature hanno un local_sys: array
f9 04 03 = 4 righe per 3 colonne = 12 numeri: tre versori e, per ultima, l'origine. Si leggono
con i numeri di §1 più un codice di ripetizione: un byte e4-e7 vale "altri K − 3 zeri",
con K = byte − e0 (e4 = 1 zero, e5 = 2, e6 = 3, e7 = 4). L'identità è quindi
0f 18 e5 0f 18 e5 0f 18 e5 = 1,0,0,0, 1,0,0,0, 1,0,0,0.
Verificato su 9239902104.prt.1 (livello 1: i valori coincidono con quelli mostrati da Creo,
sotto), con le 4 righe (e1, e2, e3, origine):
| Feature | Matrice letta | Significato |
|---|---|---|
| Foro 1 | (1,0,0) (0,0,-1) (0,1,0), origine (-46, 6, -38) |
uno dei 4 punti dello schizzo (-46, 38): x = x dello schizzo, z = **−**y dello schizzo, y = 6 = faccia superiore (la piastra è spessa 6) |
| Foro 2 | (1,0,0) (0,0,-1) (0,1,0), origine (67, 6, -5) |
71 − 4 e 5 dal bordo: le due quote 4 e 5 della feature |
| Foro 3 | (0,1,0) (-1,0,0) (0,0,1), origine (-66.5, 3, -5) |
y = 3: l'offset 3,00 dalla faccia superiore (y = 6) che Creo mostra; z = −5: allineato all'asse di Foro 2 ("Allinea" con A_7); x = −66,5 = 71 − 137,5, cioè il foro parte 137,5 prima dell'estremo destro (71) |
Quindi la posizione di un foro si legge dall'origine della sua matrice: le quote di
posizionamento (4, 5, 3,00) non servono, sono già il risultato. Nei tre fori l'y e la z tornano
esattamente con le quote e con i riferimenti mostrati da Creo.
Dalla stessa matrice: nel modello di questa piastra lo schizzo di Estrusione 1 sta nel piano x–z
(x dello schizzo = x, y dello schizzo = −z) e l'estrusione cresce lungo +y fino a 6.
Resta incerta l'interpretazione dell'asse del foro. Per Foro 1 e 2 il terzo versore è (0,1,0)
(perpendicolare alla piastra, come deve essere). Per Foro 3 è (0,0,1), ma il foro in Creo entra
dalla faccia laterale: o la convenzione del versore dell'asse è diversa, o la direzione di foratura
sta in un altro campo. Non risolto.
6.2 Dove stanno
| Cosa | Dove nel file |
|---|---|
| Piani di riferimento (RIGHT, TOP, FRONT, DTM1) | ActDatums (srf_prim_ptr(plane) con local_sys), feat_id = id della feature; vincoli di posizionamento in FeatDefsDtm (§6.3) |
Sistema di coordinate (PRT_CSYS_DEF) |
MdlRefInfo (ent_list(coord_sys)) e GeomDepen |
| Assi, punti (A_3, PNT0...) | ent_list(arc_z), ent_list(point) in MdlRefInfo |
| Piano che contiene lo schizzo | gsec3d_ptr -> plane_id, ref_planes; il piano è identificato da un id di geometria |
| Orientamento dello schizzo | sec_orient_data, place_instruction_ptrs (nella definizione di feature feat_defs_<tipo>) |
| Offset di un piano da un altro (DTM1) | quota di tipo "offset" nel dim_array della feature, se esiste |
6.3 Come è posizionato un piano: i vincoli di FeatDefsDtm
La finestra "Piano di riferimento → Posizionamento" di Creo (riferimenti con il loro vincolo,
es. Tangente a una superficie, Parallelo a un piano) si legge dal file. Sta nella sezione
FeatDefsDtm, record feat_defs_923 (un record per piano; feat_defs_926 assi, feat_defs_931
punti, feat_defs_979 sistemi di assi). Ogni record ha:
id id della feature (come in AllFeatur)
local_sys matrice 4x3 del piano risultante (§6.1)
place_instruction_ptrs una istruzione per ogni riferimento della finestra:
type codice del vincolo (intero a 2 byte)
offset double, offset del vincolo
dim_id, ref_id quota dell'offset e riferimento, se esistono
geometry1_id id della geometria a cui ci si riferisce
geometry2_id id della geometria che si sta creando (il piano stesso)
Gli id di geometria (geom_id) si risolvono nelle sezioni ActDatums (piani e assi di
riferimento), VisibGeom e NovisGeom (superfici del solido, visibili e no). Ogni voce di
srf_array ha geom_id, geom_type (", 0x22 = piano; $, 0x24 = cilindro) e feat_id: è il
legame con la feature che l'ha generata.
Verifica sul caso che hai mostrato: DTM1 di 9252000507.prt (feature 116), finestra di Creo
"Supfce:F5(RIVOLUZIONE_1) Tangente / FRONT:F3 Parallelo". Dal file:
| Istruzione | type |
geometry1_id |
Si risolve in | Corrisponde a |
|---|---|---|---|---|
| 1 | 81 fb (507) |
88 | VisibGeom: cilindro ($), feat_id 73 = Rivoluzione 1 |
"Supfce:F5(RIVOLUZIONE_1)", Tangente |
| 2 | 81 f9 (505) |
6 | ActDatums: piano ("), feat_id 5 = FRONT |
"FRONT:F3", Parallelo |
geometry2_id è 117 in entrambe: ActDatums lo dà come piano con feat_id 116 = DTM1 (il piano
risultante). Nella sua matrice compare il valore 12.5 (2f 29 00): è il raggio del cilindro,
come deve essere per un piano tangente ad esso. Il campo Traslazione della finestra era vuoto.
Quindi quali sono i riferimenti (quale feature/superficie e quale piano) si legge con certezza. Resta da fissare:
- Il significato di
type. 507 ↔ Tangente e 505 ↔ Parallelo è dedotto da un solo esempio e dall'ordine delle righe della finestra: non ho una tabella dei codici. Gli altri visti (82 01,82 02,82 03,81 fd,81 ff) sono quelli dei piani di default e degli altri piani del campione, non interpretati. Feature numberdi Creo (F3,F5): non è l'idma la posizione nel tree (RIGHT = F1, TOP = F2, FRONT = F3, PRT_CSYS_DEF = F4, Rivoluzione 1 = F5). I piani interni non contano. Per tradurre unidinF<n>si numerano le feature visibili in ordine (formato-prt-feature.md§3).- L'offset. Se un vincolo ha un offset (quota di tipo offset) il valore sta nel
dim_arraydella feature (§2) con ildim_iddell'istruzione; non ho un esempio con offset non nullo.
6.4 Il foro: feat_defs_911
Riferimento: Foro 1 di 9252000507.prt.11 (feature 157), confrontato con le schermate di Creo.
Creo mostra: tipo Standard, profilo Diritto con Maschiato, filetto ISO M8x1.25,
profondità 25, Ø6,8, profondità del filetto 20, angolo della punta 118°,
"Includi la superficie del filetto" attivo, posizionamento Coassiale con riferimenti
Supfce:F5(RIVOLUZIONE_1) e A_1(ASSE):F5(RIVOLUZIONE_1).
La definizione del foro sta nella sezione FeatDefs, record feat_defs_911. Ha due parti.
a) I parametri del filetto, in chiaro (data(ddt_plinfo_hole_fstn_param)):
| Campo | Valore letto | In Creo |
|---|---|---|
name, series |
ISO, ISO |
Tipo filetto: ISO |
scrsize |
M8x1.25 |
Dimensione vite: M8x1.25 |
scrsize_val |
0x1d (29) |
indice di M8x1.25 nella tabella delle viti di Creo (nel segnaposto M1x.25 vale 0) |
hole_class |
H |
(classe del foro) |
drillnum |
6.8 |
Ø6,8 |
b) Le istruzioni (place_instruction_ptrs): una per ogni parametro numerico, nella forma
type, offset (un double, §1), dim_id, ref_id, geometry1_id, geometry2_id. Quelle
del foro filettato, con il valore atteso da Creo:
type |
offset letto |
In Creo | Prova |
|---|---|---|---|
5104 (0x13f0) |
6,8 | Ø6,8 (anche nel foro semplice, vedi sotto) | livello 1 |
5528 (0x1598) |
118 | angolo della punta | livello 1 |
5538 (0x15a2) |
25 | profondità del foro | livello 1 |
5536 (0x15a0) |
1,25 | passo del filetto (M8x1.25) | livello 2 |
6617 (0x19d9) |
11 | non corrisponde a nulla di mostrato | non interpretato |
| 5542, 10103, 5533, 5534 | 0 | non mostrati | non interpretati |
Il codice type identifica il parametro; il valore è offset. La profondità del filetto (20) e il
diametro nominale (8) non sono istruzioni ma quote del dim_array (§2), con dim_type 9 e 4
e feat_id 157. In tutto il dim_array ha per il foro cinque quote: 8 (dim_type 4), 20 (9),
Ø6,8 (2, scritto con il tag 2e), 118 (10) e 25 (2). Tre di queste (6,8, 118, 25) compaiono
quindi due volte, come quota e come parametro di un'istruzione.
Foro semplice e foro standard. test.prt.1 ha un foro semplice: il suo feat_defs_911
è lungo 862 byte e ha solo due istruzioni (5104 con dim_id 7, e 1853); i parametri del
filetto ci sono comunque, ma con i valori segnaposto di Creo (M1x.25, drillnum 0.75,
scrsize_val 0): quindi le stringhe scrsize/drillnum da sole non dicono se il foro è
filettato. Quello di Fata ha 3212 byte e 12 istruzioni, valori diversi dal segnaposto. Il segno
affidabile oggi è: foro standard = presenza delle istruzioni 5536 (passo) e 5528 (angolo punta),
e il foro è filettato quando anche i valori del filetto non sono quelli segnaposto.
Non individuato nel file (per ognuno servono due salvataggi che differiscono solo per quell'opzione):
- Maschiato / Trapanato / Gioco, Diritto / Rastremato: non so quale istruzione o flag le
codifichi.
plin_info_hole_flag.flagsvale2, 2in entrambi i fori. - Includi la superficie del filetto: idem.
- Il tipo Standard/Semplice come campo esplicito: oggi si deduce solo dal numero di istruzioni.
Posizionamento Coassiale. Gli ingredienti ci sono: un blocco data(plin_info_ref) per ogni
riferimento, con gli id di geometria. Il piano del riferimento Supfce:F5 dovrebbe essere la
faccia piana di Rivoluzione 1 (feature 73, in VisibGeom con feat_id 73) e il secondo
riferimento l'asse A_1: non ho agganciato quegli id perché le coppie id_type1/id_type2 non le
ho decifrate. La geometria generata dal foro (cilindro, cono, piani con feat_id 157) è invece
in VisibGeom e NovisGeom, e geometry2_id 175 delle istruzioni è un suo piano.
6.4.1 Foro a punti di schizzo e facce piane: 9239902104.prt.1
Foro 1 è definito da Sketch 2 con 4 punti. Cosa si legge, tutto da local_sys (§6.1):
I punti. Nello schizzo (entity(point), campo pnt, un [x, y, z] per punto) sono
(-46, 8), (-8, 8), (-8, 38), (-46, 38), con quote 8, 8, 30 e 38. Nel modello ogni punto
diventa un'istanza del foro, e ogni istanza ha un piano proprio in NovisGeom (superficie
piana con feat_id 131, §6.3) con la matrice del punto: l'origine è la posizione assoluta.
Piano (geom_id) |
Origine nel modello |
|---|---|
| 135 | (-46, 6, -8) |
| 147 | (-8, 6, -8) |
| 159 | (-8, 6, -38) |
| 171 | (-46, 6, -38) |
Quindi x = x dello schizzo, z = −y dello schizzo (confermato dai quattro punti e da Foro
2, §6.1) e y = 6.
La faccia. La superficie su cui stanno è la faccia piana superiore di Estrusione 1: ha
y = 6 e la stessa matrice del sistema di coordinate dello schizzo (origine (0, 6, 0),
versori (1,0,0), (0,0,1), (0,-1,0)). Le facce piane di Estrusione 1 (feat_id 84, in
VisibGeom) sono, con origine e normale (il terzo versore):
geom_id |
Origine | Normale | Faccia |
|---|---|---|---|
| 95 | (0, 6, 0) |
(0,-1,0) |
superiore (y = 6), dove sono i fori |
| 107 | (71, 0, 0) |
(-1,0,0) |
estremo destro (x = 71) |
| 113 | (-54, 0, -46) |
(1,0,0) |
estremo sinistro (x = -54) |
| 115 | (-54, 0, 0) |
(0,0,1) |
lato z = 0 |
| 2999 | (71, 0, -21) |
(0,0,-1) |
lato del gradino (z = -21) |
| 3001 | (0, 0, -21) |
(-1,0,0) |
alzata del gradino (x = 0) |
| 3003 | (0, 0, -46) |
(0,0,-1) |
lato z = -46 |
La piastra a L di Estrusione 1 (§3.2, profilo x da −54 a 71, y dello schizzo da 0 a 46, gradino
a 21) torna in coordinate modello con z = −y dello schizzo, e spessore 6 lungo y. Gli altri
tre fori cadono dentro il materiale (x −46 e −8, z −8 e −38).
Non risolto: quale geom_id il foro usi formalmente come faccia di riferimento (95, per
coincidenza di piano e di origine) non è scritto in un campo che io abbia identificato: è
un'identificazione per posizione, non una lettura.
6.5 Lo smusso: feat_defs_914
Riferimento: Smusso 1 di 9252000507.prt.11 (feature 252), in modifica in Creo: modalità
Insiemi, schema quote D x D con D = 0.500, un insieme ("Insieme 1") con due
riferimenti, entrambi Spigolo:F5(RIVOLUZIONE_1), e l'opzione "Superfici con offset".
| Cosa | Dove | Letto | Prova |
|---|---|---|---|
| Valore D | dim_array, feat_id 252, dim_type 9 |
0e = 0,5 |
livello 1 |
Valore in test.prt.1 |
dim_array, feat 188, dim_type 9 |
2f 18 00 = 6,0 |
livello 2 |
| Superfici del bordo | feat_defs_914, istruzioni di tipo 4530 |
geometry1_id = 88, 86, 106, 90 |
vedi sotto |
| Superfici generate dallo smusso | VisibGeom, feat_id 252 |
superfici coniche (geom_id 253, 258, 261, 266) |
presenti |
Il dim_type 9 è lo stesso del foro (profondità del filetto): dice la classe della quota, non
cosa misura. Per lo smusso vale D, ma la stessa classe in un foro vale 20.
I riferimenti. Le istruzioni di tipo 4530 hanno nel campo geometry1_id gli id 88, 86, 106 e
90, ripetuti a coppie. Risolti con VisibGeom: 88 e 106 sono superfici cilindriche con
feat_id 73 (cioè Rivoluzione 1, F5), 86 è il piano di estremità della stessa rivoluzione
(visto in §3.1 e §6.3). Quindi i riferimenti Spigolo:F5(RIVOLUZIONE_1) sono spigoli ricavati dalle
superfici di Rivoluzione 1, come mostra Creo. Non so ancora quale coppia di id formi quale
spigolo, né a quale dei due "Spigolo" della lista corrisponda (le istruzioni non sono in un ordine
che io abbia decifrato), e 90 non l'ho risolto.
Non decodificato:
- lo schema quote (D x D, D1 x D2, angolo x D...): non ho trovato dove sta; compaiono vari tipi di
istruzione (
7350,7360,4549,4552,4557,4558,1125,7265,14741) senza corrispondenza con le voci mostrate; - "Insieme 1" e la sua composizione: compare la struttura (
data(plin_info_chut_info), array di riferimenti) ma non la ho letta; - "Superfici con offset" e il tipo di transizione;
- l'istruzione
14741, con un valore11,476in precisione piena: non corrisponde a niente di mostrato.
Foro filettato con posizionamento lineare (Foro 3 di 9239902104.prt.1). Creo mostra: tipo
Standard, Diritto, Maschiato, ISO M3x.5, Ø2,50 (punta), campo profondità vuoto, posizionamento
Lineare con riferimento primario Supfce:F6(ESTRUSIONE_1) e due riferimenti di offset
(Supfce:F6(ESTRUSIONE_1) con offset 3,00 e A_7(ASSE):F10(FORO 2) allineato). Dal file:
| Informazione | Letto | Prova |
|---|---|---|
| Filetto | stringhe ISO, M3x.5, punta 2.5; scrsize_val = 12 |
concorda con Creo |
| Ø della punta | istruzione 5104, offset 2,5 | concorda con Creo (Ø2,50) |
| Quote del foro | 3 (dim_type 4), 6 (9), 2,5 (2), 137,5 (2) |
numeri letti; 137,5 con campo "Profondità" vuoto in Creo: probabilmente un foro passante, valore non verificato |
Posizione risultante (offset 3,00 e allineamento a A_7) |
letta dalla matrice local_sys (§6.1): origine (-66.5, 3, -5), con y = 3 e z = −5 uguali a quelli di Foro 2 |
concorda con Creo; la quota 3,00 non è una quota a sé nel dim_array |
Riferimenti F6 e A_7 |
non risolti | gli id stanno in blocchi plin_info_ref come per DTM1 (§6.3) |
Correzione: il primo codice delle istruzioni è 5542 anche qui, come nel foro coassiale di
9252000507; il 12266 che avevo letto nella prima versione di questo doc veniva da un'istruzione
di un altro record. Il tipo di posizionamento (coassiale / lineare) non è quel codice. Quale sia
non lo so: la posizione finale si legge comunque dalla matrice (§6.1).
7. Cosa manca per determinare un .prt in modo univoco
Tabella di verità: ogni informazione necessaria, se l'ho decodificata e quanto è provata.
| Informazione | Stato | Dove si trova |
|---|---|---|
| Elenco e ordine delle feature | fatto, provato (test.prt.1, 9252000507.prt.11 contro Creo) |
AllFeatur |
| Tipo di ogni feature | fatto; estrusione vs rivoluzione solo con lo storico | AllFeatur, storico |
| Nome di ogni feature | fatto, ma solo se esiste lo storico (10 file su 31 leggibili) | MdlStatus |
| Quote (valori numerici) | fatto per i valori interi/semplici, tag 2f/48 |
dim_array |
| Significato di ogni quota | parziale: provato solo per Rivoluzione 1 | dim_type (§2.1) |
| Geometria dello schizzo (linee) | fatto per le linee, provato su Rivoluzione 1 | p_saved_result |
| Cerchi, archi, spline dello schizzo | non verificato (cerchio visto in test.prt.1, raggio 50) |
entity(circle), entity(arc_z), entity(spline) |
| Valori non "tondi" | non decodificato (tag diversi da 2f/48) |
ovunque |
| Piano e orientamento dello schizzo | non decodificato | gsec3d_ptr, sec_orient_data |
| Posizione/rotazione di fori e feature | fatto: matrice 4×3 (§6.1) | local_sys |
| Posizione/rotazione di piani, assi, punti | stessa matrice, da verificare su un piano ruotato | ActDatums, MdlRefInfo |
| Vincoli e riferimenti di un piano (come DTM1) | fatto per DTM1 di 9252000507 (riferimenti sì, nome del vincolo da un esempio) |
FeatDefsDtm, §6.3 |
| Offset di un piano da un altro | non decodificato: mai visto un offset non nullo | quota in dim_array (dim_id) |
| Direzione/lato e angolo di una rivoluzione, profondità e direzione di un'estrusione | non decodificato | feat_defs_917/916 (place_instruction_ptrs, plin_info_arr) |
| Parametri del foro (misura, punta, passo, profondità, angolo) | fatto, provato contro Creo su 9252000507 |
feat_defs_911, §6.4 |
| Opzioni del foro (maschiato, diritto, superficie del filetto) | non individuato | §6.4 |
| Posizione assoluta del foro (origine e versori) | fatto, provato contro i riferimenti di Creo su 9239902104 (§6.1) |
local_sys del record |
| Riferimenti del posizionamento (quale faccia/asse) | non decodificato | plin_info_ref in feat_defs_911 |
| Valore di raccordi e smussi | fatto, provato contro Creo su 9252000507 (D = 0,5) |
dim_array |
| Spigoli a cui si applicano raccordi/smussi | parziale: si risolvono le superfici (feature di origine), non lo spigolo né l'insieme | feat_defs_914, §6.5 |
| Schema quote e insiemi dello smusso | non decodificato | feat_defs_914 |
| Tolleranze (h7...) | non decodificato | blocco tol_ptr del dim_array |
| Unità di misura | non letto | UnitSystemDef (sezione compressa) |
| Feature nascoste / soppresse | non decodificato | non individuato nel file |
| Parametri e materiale | parziale, via ND:0:Model_* (XML) |
sezione compressa .Z |
| File Wildfire (generazioni 1322/1375/1376) | illeggibile (sezioni di tipo 11) |
formato-prt-feature.md §1.3 |
Conclusione onesta: oggi si ricava con affidabilità quali feature ci sono, che tipo sono, come si chiamano (se c'è lo storico), quanto misurano le quote semplici e che forma ha lo schizzo se fatto di linee con numeri semplici. Non si ricava ancora dove stanno nello spazio né come sono orientate, né si può ricostruire il solido completo.
8. Come finire il lavoro
Per ogni riga "non decodificato" della §7 il metodo è lo stesso, ed è quello che ha dato Rivoluzione 1:
- Scegliere un
.prtpiccolo con una sola feature del tipo da decodificare, e annotare da Creo i valori veri (quote, posizione dei piani, angolo, direzione). - Estrarre da
BasFullData/ActDatumsi record di quella feature e cercarvi quei numeri con il decodificatore di §1: i valori noti ancorano i byte. - Variare una cosa alla volta nel modello (spostare il piano, cambiare l'angolo), risalvare e confrontare i due file: i byte che cambiano sono il campo cercato.
- Registrare in questo doc il campo, con il file di prova e il valore atteso, come in §5.
Tre modelli di prova che chiuderebbero la maggior parte della §7: un piano DTM1 a offset non nullo
dal piano TOP (e con un vincolo Attraverso, Normale, Offset...); una estrusione di profondità nota su un piano ruotato; una rivoluzione di 90°.
Una volta chiusa la §7 il passo successivo è un PrtModelReader in C# accanto ad AsmRecordReader,
con le stesse regole: se un valore non si decodifica si solleva InvalidDataException, non si
restituisce un modello parziale in silenzio.