use std::fmt::Write as FmtWrite;
#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq)]
pub enum IgesSection {
Start,
Global,
Directory,
Parameter,
Terminate,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct IgesExportConfig {
pub author: String,
pub organisation: String,
pub originating_system: String,
pub description: String,
pub version: String,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct IgesEntity {
pub seq: u32,
pub entity_type: u16,
pub param_data: String,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct IgesDocument {
pub config: IgesExportConfig,
pub entities: Vec<IgesEntity>,
next_seq: u32,
}
#[allow(dead_code)]
pub fn default_iges_config() -> IgesExportConfig {
IgesExportConfig {
author: "OxiHuman".to_string(),
organisation: "COOLJAPAN OU".to_string(),
originating_system: "OxiHuman IGES Exporter 1.0".to_string(),
description: "IGES export generated by OxiHuman".to_string(),
version: "5.3".to_string(),
}
}
#[allow(dead_code)]
pub fn new_iges_document(cfg: &IgesExportConfig) -> IgesDocument {
IgesDocument {
config: cfg.clone(),
entities: Vec::new(),
next_seq: 1,
}
}
#[allow(dead_code)]
pub fn iges_add_point(doc: &mut IgesDocument, x: f64, y: f64, z: f64) -> u32 {
let seq = doc.next_seq;
doc.next_seq += 1;
doc.entities.push(IgesEntity {
seq,
entity_type: 116,
param_data: format!("{x:.6},{y:.6},{z:.6}"),
});
seq
}
#[allow(dead_code)]
pub fn iges_add_line(
doc: &mut IgesDocument,
x1: f64,
y1: f64,
z1: f64,
x2: f64,
y2: f64,
z2: f64,
) -> u32 {
let seq = doc.next_seq;
doc.next_seq += 1;
doc.entities.push(IgesEntity {
seq,
entity_type: 110,
param_data: format!("{x1:.6},{y1:.6},{z1:.6},{x2:.6},{y2:.6},{z2:.6}"),
});
seq
}
#[allow(dead_code)]
pub fn iges_to_string(doc: &IgesDocument) -> String {
let mut out = String::new();
out.push_str(&iges_header_string(doc));
let _ = writeln!(
out,
"{}",
iges_section_line(&format!("{}G 1", doc.config.originating_system), 'G', 1)
);
for ent in &doc.entities {
let dir_line = format!("{:8} 0 0 0 0", ent.entity_type);
let _ = writeln!(out, "{}D{:7}", dir_line, ent.seq);
let param_line = format!("{},{};", ent.entity_type, ent.param_data);
let _ = writeln!(out, "{}P{:7}", param_line, ent.seq);
}
let _ = writeln!(
out,
"S 1G 1D{:6}P{:6} T 1",
doc.entities.len(),
doc.entities.len()
);
out
}
#[allow(dead_code)]
pub fn iges_write_to_file(doc: &IgesDocument, path: &str) -> Result<(), String> {
let content = iges_to_string(doc);
std::fs::write(path, content).map_err(|e| e.to_string())
}
#[allow(dead_code)]
pub fn iges_entity_count(doc: &IgesDocument) -> usize {
doc.entities.len()
}
#[allow(dead_code)]
pub fn iges_section_name(section: IgesSection) -> &'static str {
match section {
IgesSection::Start => "Start",
IgesSection::Global => "Global",
IgesSection::Directory => "Directory",
IgesSection::Parameter => "Parameter",
IgesSection::Terminate => "Terminate",
}
}
#[allow(dead_code)]
pub fn iges_header_string(doc: &IgesDocument) -> String {
format!(
"{}S 1\n",
iges_section_line(
&format!("{};", doc.config.description),
'S',
1
)
)
}
#[allow(dead_code)]
pub fn iges_document_clear(doc: &mut IgesDocument) {
doc.entities.clear();
doc.next_seq = 1;
}
fn iges_section_line(content: &str, section: char, _seq: u32) -> String {
let max_content = 72;
let trimmed: String = content.chars().take(max_content).collect();
format!("{:<72}{}", trimmed, section)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config_fields() {
let cfg = default_iges_config();
assert!(!cfg.author.is_empty());
assert!(!cfg.organisation.is_empty());
assert!(!cfg.originating_system.is_empty());
assert!(!cfg.version.is_empty());
}
#[test]
fn test_new_document_empty() {
let cfg = default_iges_config();
let doc = new_iges_document(&cfg);
assert_eq!(iges_entity_count(&doc), 0);
}
#[test]
fn test_add_point_increments_count() {
let cfg = default_iges_config();
let mut doc = new_iges_document(&cfg);
iges_add_point(&mut doc, 1.0, 2.0, 3.0);
assert_eq!(iges_entity_count(&doc), 1);
}
#[test]
fn test_add_point_returns_sequential_ids() {
let cfg = default_iges_config();
let mut doc = new_iges_document(&cfg);
let id1 = iges_add_point(&mut doc, 0.0, 0.0, 0.0);
let id2 = iges_add_point(&mut doc, 1.0, 0.0, 0.0);
assert_eq!(id1, 1);
assert_eq!(id2, 2);
}
#[test]
fn test_add_line_entity_type() {
let cfg = default_iges_config();
let mut doc = new_iges_document(&cfg);
iges_add_line(&mut doc, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0);
assert_eq!(doc.entities[0].entity_type, 110);
}
#[test]
fn test_iges_to_string_contains_terminate() {
let cfg = default_iges_config();
let doc = new_iges_document(&cfg);
let s = iges_to_string(&doc);
assert!(s.contains('T'));
}
#[test]
fn test_iges_to_string_has_start_section() {
let cfg = default_iges_config();
let doc = new_iges_document(&cfg);
let s = iges_to_string(&doc);
assert!(s.contains('S'));
}
#[test]
fn test_iges_section_name_all_variants() {
assert_eq!(iges_section_name(IgesSection::Start), "Start");
assert_eq!(iges_section_name(IgesSection::Global), "Global");
assert_eq!(iges_section_name(IgesSection::Directory), "Directory");
assert_eq!(iges_section_name(IgesSection::Parameter), "Parameter");
assert_eq!(iges_section_name(IgesSection::Terminate), "Terminate");
}
#[test]
fn test_iges_header_string_not_empty() {
let cfg = default_iges_config();
let doc = new_iges_document(&cfg);
let hdr = iges_header_string(&doc);
assert!(!hdr.is_empty());
}
#[test]
fn test_document_clear_resets_count() {
let cfg = default_iges_config();
let mut doc = new_iges_document(&cfg);
iges_add_point(&mut doc, 0.0, 0.0, 0.0);
iges_document_clear(&mut doc);
assert_eq!(iges_entity_count(&doc), 0);
}
#[test]
fn test_clear_resets_sequence() {
let cfg = default_iges_config();
let mut doc = new_iges_document(&cfg);
iges_add_point(&mut doc, 0.0, 0.0, 0.0);
iges_document_clear(&mut doc);
let id = iges_add_point(&mut doc, 1.0, 2.0, 3.0);
assert_eq!(id, 1);
}
#[test]
fn test_point_entity_type() {
let cfg = default_iges_config();
let mut doc = new_iges_document(&cfg);
iges_add_point(&mut doc, 5.0, 6.0, 7.0);
assert_eq!(doc.entities[0].entity_type, 116);
}
#[test]
fn test_line_param_data_contains_coords() {
let cfg = default_iges_config();
let mut doc = new_iges_document(&cfg);
iges_add_line(&mut doc, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
assert!(doc.entities[0].param_data.contains("1.000000"));
assert!(doc.entities[0].param_data.contains("6.000000"));
}
}