Files
dxftogcode/dxfutil/dxf_util.go
John Thornton 90c48ae594 GUI creates the ini file now and add layers
Signed-off-by: John Thornton <bjt128@gmail.com>
2015-11-05 08:20:53 -06:00

247 lines
5.6 KiB
Go

package dxfutil
import (
"bufio"
"os"
"fmt"
"math"
"strconv"
"strings"
"sort"
)
type Ent struct {
Test, Index int
G0, G, G8, G10, G11, G20, G21, G30, G31, G40, G50, G51 string
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 }
// add float compare
var EPSILON float64 = 0.0001
func floatCompare(a, b float64) bool {
if ((a - b) < EPSILON && (b - a) < EPSILON) {
return true
}
return false
}
func formatString (s string) (r string) {
p := strings.Index(s, ".")
if p == -1 {
s += "."
p = strings.Index(s, ".")
}
for i := len(s[p+1:])-5 ; i < 0 ; i++ {
s += "0"
}
if len(s[p+1:]) > 5 {s = s[:p+6]} // trim decimal places to 5
return s
}
func Round(f float64) float64 {
return math.Floor(f + .5)
}
func RoundPlus(f float64, places int) (float64) {
shift := math.Pow(10, float64(places))
return Round(f * shift) / shift;
}
func getXcartesian(r, a, x string) (float64){
radius, _ := strconv.ParseFloat(r, 64)
angle, _ := strconv.ParseFloat(a, 64)
offset, _ := strconv.ParseFloat(x, 64)
return RoundPlus(radius * math.Cos(angle * (math.Pi / 180)), 4) + offset
}
func getYcartesian(r, a, y string) (c float64){
radius, _ := strconv.ParseFloat(r, 64)
angle, _ := strconv.ParseFloat(a, 64)
offset, _ := strconv.ParseFloat(y, 64)
return RoundPlus(radius * math.Sin(angle * (math.Pi / 180)), 4) + offset
}
func GetLines(f string) ([]string) {
lines := []string{}
file, err := os.Open(f)
defer file.Close()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
inEntities := false
for scanner.Scan() {
switch scanner.Text() {
case "ENTITIES":
inEntities = true
case "ENDSEC":
inEntities = false
}
if inEntities {
lines = append(lines, scanner.Text())
}
}
fmt.Println("GetLines Done")
return lines
}
func GetEntities(list []string) ([]Ent){
// add error handling
group := ""
count := 0
var e []Ent
for i := range list {
if len(group) > 0 {
switch group {
case " 0":
if len(e) > 0 {count++}
e = append(e, Ent{})
e[count].Test = count
e[count].G0 = list[i]
case " 8":
e[count].G8 = list[i]
case " 10":
e[count].G10 = formatString(list[i])
case " 11":
e[count].G11 = formatString(list[i])
case " 20":
e[count].G20 = formatString(list[i])
case " 21":
e[count].G21 = formatString(list[i])
case " 30":
e[count].G30 = formatString(list[i])
case " 31":
e[count].G31 = formatString(list[i])
case " 40":
e[count].G40 = formatString(list[i])
case " 50":
e[count].G50 = formatString(list[i])
case " 51":
e[count].G51 = formatString(list[i])
}
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]
}
}
fmt.Println("GetEntities Done")
return e
}
func GetLayers(e []Ent){
var layers []string
Search:
for i := range e {
if len(layers) == 0 {
layers = append(layers, e[i].G8)
continue Search
}
for j := range layers {
if e[i].G8 == layers[j]{ continue Search }
}
layers = append(layers, e[i].G8)
}
fmt.Println("Layers", layers)
}
func GetEndPoints (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, _ = strconv.ParseFloat(e[i].G10, 64)
e[i].Ys, _ = strconv.ParseFloat(e[i].G20, 64)
e[i].Zs, _ = strconv.ParseFloat(e[i].G30, 64)
e[i].Xe, _ = strconv.ParseFloat(e[i].G11, 64)
e[i].Ye, _ = strconv.ParseFloat(e[i].G21, 64)
e[i].Zs, _ = strconv.ParseFloat(e[i].G31, 64)
case "CIRCLE":
fmt.Println("Circles not supported at this time")
os.Exit(1)
case "SPLINE":
fmt.Println("Splines not supported at this time")
os.Exit(1)
}
}
fmt.Println("GetEndPoints Done")
return e
}
func GetOrder(e []Ent) ([]Ent) {
c := 3 // entity to search from
dir := "CW" // direction of travel
Search:
for i := range e {
if i == len(e) - 1 { break } // don't process the last one
// if direction is CW and it is an arc reverse the arc before processing
if i == 0 { // this will need to be smarter to figure out if it is G2 or G3
switch e[c].G0 {
case "ARC":
if dir == "CW" {
e[c].G = "2"
e[c].Xe, e[c].Xs = e[c].Xs, e[c].Xe
e[c].Ye, e[c].Ys = e[c].Ys, e[c].Ye
e[c].G50, e[c].G51 = e[c].G51, e[c].G50
} else {
e[c].G = "3"
}
case "LINE":
e[c].G = "1"
}
}
for j := range e {
if c != j && floatCompare(e[c].Xe, e[j].Xs) && floatCompare(e[c].Ye, e[j].Ys) {
e[j].Index = i + 1
c = j
switch e[j].G0 {
case "ARC":
e[j].G = "3"
case "LINE":
e[j].G = "1"
}
continue Search
}
}
for k := range e {
if c != k && floatCompare(e[c].Xe, e[k].Xe) && floatCompare(e[c].Ye, e[k].Ye) {
// swap end points
e[k].Xe, e[k].Xs = e[k].Xs, e[k].Xe
e[k].Ye, e[k].Ys = e[k].Ys, e[k].Ye
e[k].Index = i + 1
c = k
switch e[k].G0 {
case "ARC":
e[k].G = "2"
e[k].G50, e[k].G51 = e[k].G51, e[k].G50
case "LINE":
e[k].G = "1"
e[k].G10, e[k].G11 = e[k].G11, e[k].G10
e[k].G20, e[k].G21 = e[k].G21, e[k].G20
}
continue Search
}
}
}
sort.Sort(ByIndex(e))
fmt.Println("GetOrder Done")
return e
}