package main // dxf2g version 0.0000001 import ( "bufio" "os" "os/user" "fmt" "strconv" "math" "sort" "github.com/jethornton/dxfutil" ) func check(e error) { if e != nil { panic(e) os.Exit(0) } } /* func iniRead(m map[string]string, home string) { home += "/dxf2gcode.ini" f, err := os.Open(home) check(err) defer f.Close() scanner := bufio.NewScanner(f) for scanner.Scan() { line := scanner.Text() parts := strings.Split(line, "=") for range parts { m[parts[0]] = parts[1] } } } */ func getXcartesian(radius, angle float64) (coordinate float64){ return radius * math.Cos(angle * (math.Pi / 180)) } func getYcartesian(radius, angle float64) (coordinate float64){ return radius * math.Sin(angle * (math.Pi / 180)) } func getLines(filename string) ([]string) { lines := []string{} f, err := os.Open(filename) defer f.Close() if err != nil { fmt.Println(err) os.Exit(1) } scanner := bufio.NewScanner(f) scanner.Split(bufio.ScanLines) inEntities := false // extract all the lines of entities for scanner.Scan() { switch scanner.Text() { case "ENTITIES": inEntities = true case "ENDSEC": inEntities = false } if inEntities { lines = append(lines, scanner.Text()) } } return lines } func getEnt(list []string, e []Ent) ([]Ent){ // add error handling group := "" count := 0 for i := range list { if len(group) > 0 { switch group { case " 0": if len(e) > 0 {count++} e = append(e, Ent{}) e[count].G0 = list[i] case " 8": e[count].G8 = list[i] case " 10": e[count].G10, _ = strconv.ParseFloat(list[i],64) case " 11": e[count].G11, _ = strconv.ParseFloat(list[i],64) case " 20": e[count].G20, _ = strconv.ParseFloat(list[i],64) case " 21": e[count].G21, _ = strconv.ParseFloat(list[i],64) case " 30": e[count].G30, _ = strconv.ParseFloat(list[i],64) case " 31": e[count].G31, _ = strconv.ParseFloat(list[i],64) case " 40": e[count].G40, _ = strconv.ParseFloat(list[i],64) case " 50": e[count].G50, _ = strconv.ParseFloat(list[i],64) case " 51": e[count].G51, _ = strconv.ParseFloat(list[i],64) } group = "" } switch list[i] { // trigger when a group is found case " 0", " 8", " 10", " 11", " 20", " 21", " 30", " 31", " 40", " 50", " 51": group = list[i] } } return e } func findEndPoints (e []Ent) ([]Ent){ // add error handling for i := range e { switch e[i].G0 { case "ARC": // get the X and Y end points e[i].Xs = getXcartesian(e[i].G40, e[i].G50) + e[i].G10 e[i].Xe = getXcartesian(e[i].G40, e[i].G51) + e[i].G10 e[i].Ys = getYcartesian(e[i].G40, e[i].G50) + e[i].G20 e[i].Ye = getYcartesian(e[i].G40, e[i].G51) + e[i].G20 case "LINE": e[i].Xs = e[i].G10 e[i].Ys = e[i].G20 e[i].Zs = e[i].G30 e[i].Xe = e[i].G11 e[i].Ye = e[i].G21 e[i].Zs = e[i].G31 case "CIRCLE": // if it is a circle it must be the only entity on that layer fmt.Println("Circle") } } return e } // find the matching start points for each entity and assign index func findIndex(s int, t string, e []Ent) ([]Ent) { // add error handling xe := e[s].Xe ye := e[s].Ye index := 1 tol, err := strconv.ParseFloat(t, 64) check(err) for skip, _ := range e { if skip != s { for i := range e { if math.Abs(e[i].Xs - xe) < tol && math.Abs(e[i].Ys - ye) < tol { e[i].Index = index index++ xe = e[i].Xe ye = e[i].Ye break } } } } return e } type Ent struct { Index int G0, G8 string G10, G11, G20, G21, G30, G31, G40, G50, G51, Xs, Xe, Ys, Ye, Zs, Ze float64 } type ByIndex []Ent func (a ByIndex) Len() int { return len(a) } func (a ByIndex) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByIndex) Less(i, j int) bool { return a[i].Index < a[j].Index } func genGcode (e []Ent, fileout string) { /* need to figure out if the start point of first entity and the end point of the last entity are the same if so then make the last move to the start point. */ xo, yo := 0.0, 0.0 feed := 25.0 //outfile := "/home/john/linuxcnc/nc_files/output.ngc" f, err := os.Create(fileout) if err != nil { fmt.Println(err) os.Exit(1) } defer f.Close() fmt.Fprintf(f, "G0 X%f Y%f\n", e[0].Xs, e[0].Ys) fmt.Fprintf(f, "F%.1f\n",feed) for _, ent := range e { switch ent.G0 { case "LINE": fmt.Fprintf(f, "G1 X%.4f Y%.4f\n", ent.G11, ent.G21) case "ARC": switch { case ent.G50 <= 90.0: xo = -(ent.Xs - ent.G10) yo = -(ent.Ys - ent.G20) case ent.G50 > 90 && ent.G50 <= 180.0: xo = math.Abs(ent.Xs - ent.G10) yo = -(ent.Ys - ent.G20) case ent.G50 > 180 && ent.G50 <= 270.0: xo = math.Abs(ent.Xs - ent.G10) yo = math.Abs(ent.Ys - ent.G20) case ent.G50 > 270 && ent.G50 <= 360.0: xo = -(ent.Xs - ent.G10) yo = -(ent.Ys - ent.G20) } fmt.Fprintf(f, "G3 X%.4f Y%.4f I%.4f J%.4f\n", ent.Xe, ent.Ye, xo, yo) case "CIRCLE": fmt.Println("Circle") } } fmt.Fprintf(f, "M2") fmt.Println("Processing Done.") } func main(){ usr, err := user.Current() check(err) iniMap := make(map[string]string) var inFile string if len(os.Args) == 2 { switch os.Args[1]{ case "-v": fmt.Println("Version 0.001") os.Exit(0) default: inFile = os.Args[1] } } else { pwd, err := os.Getwd() check(err) fmt.Println("Current Working Directory is:", pwd) fmt.Println("Current User Directory is:", usr.HomeDir) fmt.Println("Usage is: dxf2g filename.ext") fmt.Println("Usage is: dxf2g -v") fmt.Println(dxfutil.Import("c")) os.Exit(0) } dxfutil.Readini(iniMap, usr.HomeDir) var entities []Ent lines := getLines(inFile) entities = getEnt(lines, entities) entities = findEndPoints(entities) start := 1 entities = findIndex(start, iniMap["TOLERANCE"], entities) sort.Sort(ByIndex(entities)) genGcode(entities, iniMap["SAVEAS"]) }