Hello, this is my first post on this forum.
I'm a novice in rust, but I think I have found a good application which will allow me to dive a bit deeper.
I have a bunch of SCADA screens drawn in autocad.
These have to be translated to cimplicity screens.
I am currently trying to modify this dxf2svg code to generate ctx files.
I export the autocad drawings into dxf format. Now I am rewriting the part of the code that generates a svg-file to generate a ctx-file instead.
I added a new ctx.rs file in the project to hold the data to generate the ctx-file.
I have this structure stubbed out at the moment in a new file ctx.rs:
#[derive(Debug, Clone)]
pub struct CtxDoc {
pub version : i32, // for the ctx-file header
pub data : Vec<CtxObjects>, // a vec of enum
pub test_data : Vec<String>, // Just a test (to be replaced with data)
}
#[derive(Debug, Clone)]
pub enum CtxObjects{
Text(CtxText), //a struct with all info needed to generate the text in the ctx-file
Line(CtxLine), //a struct with all info needed to generate the line in the ctx-file
// ...
}
#[derive(Debug, Clone)]
pub struct CtxLine {
pub pos : Position, // from coord.rs (already in dxf2svg)
pub name : String,
// .. color, width, ...
}
// some code to generate the ctx-file from the CtxDoc struct by looping over the vec of CtxObjects
To populate the vec of CtxObjects, I renamed dxf2svg as dxf2ctx.
This holds the code that generates nodes for the svg document, which I am now trying to modify to populate CtxObjects instead.
Here is a snippet where it loops over the entities that it found in the dxf-file and adds the corresponding svg-node to the document.
match &entity.specific {
EntityType::LwPolyline(polyline) => {
//let polyline = polyline.clone();
//let points: Vec<(f64, f64)> = polyline
// .vertices
// .into_iter()
// .map(|vertex| (coord.relative_to((vertex.x.clone(), vertex.y.clone()))))
// .collect();
//let node = Polyline::new()
// .points(points)
// .stroke(&color)
// .stroke_width(line_weight);
//document.add(node);
// <snip> some code to generate a String that represents a line in ctx-file format
&document.test_data.push(MyString);
}
So I managed to make document a CtxDoc-struct.
But how do I implement the add methods for the different CtxObjects (CtxText, CtxLine, ...)?
EDIT:
I added an enum CtxObject and a Vec. Now I'm stuck, trying to call a method to output ctx format for CtxText or CtxLine based on the type like so:
#[derive(Debug, Clone)]
pub enum CtxObject{ // the enum can have these types
Line(CtxLine),
Text(CtxText),
// ..
}
impl CtxObject {
pub fn ctxify(self : &Self) -> String {
// Match the type of CtxObject and call the ctxify method of that type
match self {
CtxLine => self.line_ctxify(), // this does not work
CtxText => self.text_ctxify(), // this does not work
_ => String::from("UNHANDLED"),
}
}
}
It looks like I can only call methods that are implemented for CtxObject.
I've looked around for something similar but haven't found a solution yet.
EDIT2: This works, but I'm not sure how. (I also don't like that I have to clone the objects)
#[derive(Debug, Clone)]
pub struct CtxDoc {
pub version : i32,
pub test : String,
pub data : Vec<CtxObject>, // this is an enum
}
#[derive(Debug, Clone)]
pub enum CtxObject{ // the enum can have these types
Line(CtxLine),
Text(CtxText),
// ..
}
impl CtxObject {
pub fn ctxify(self : &Self) -> String {
// Match the type of CtxObject and call the ctxify method of that type
let obj =self.clone();
//match self {
// CtxLine => line_ctxify(obj),
// CtxText => text_ctxify(CtxObject::Text(obj)), //CtxObject::Text(self)
// _ => String::from("UNHANDLED"),
// }
if let CtxObject::Text(text) = obj {text.text_ctxify()}
else { String::from("UNHANDLED") }
}
}
// Move this line to a separate .rs and import it?
#[derive(Debug, Clone)]
pub struct CtxLine {
pub name : String,
pub width : i32,
// .. color, width, ...
}
impl CtxLine {
pub fn line_ctxify(self: Self)->String { //should probably be string or error?
String::from("Line to ctx")
}
}
#[derive(Debug, Clone)]
pub struct CtxText {
pub name : String,
pub position : (i32,i32),
// .. color, width, ...
}
impl CtxText {
pub fn text_ctxify(self: Self)->String { //should probably be string or error?
self.name
}
}
impl CtxDoc {
pub fn new() -> Self {
CtxDoc{
version : 57,
test : String::from("TEST"),
data : Vec::new(),
}
}
pub fn add_ctx_line(self: &mut Self, line:CtxLine) -> anyhow::Result<()>{
self.data.push(CtxObject::Line(line));
Ok(())
}
pub fn add_ctx_text(self: &mut Self, text:CtxText) -> anyhow::Result<()>{
self.data.push(CtxObject::Text(text));
Ok(())
}
pub fn save(self: & Self) -> anyhow::Result<()> { //Result<(), Error> {
let path = "test.ctx";
let mut output = File::create(path)?;
write!(output, "{}", &self.header_stuff());
for data in &self.data {
// call the ctxify of the type
write!(output, "{:?}\r\n", data.ctxify());
}
write!(output, "{}", &self.footer_stuff());
Ok(())
}