Dwg2ctx converter

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(())
    }

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.