Skip to content

Instantly share code, notes, and snippets.

@picatz
Created August 28, 2023 21:42
Show Gist options
  • Save picatz/902576fea4bb82e2029b2ff2d02fa426 to your computer and use it in GitHub Desktop.
Save picatz/902576fea4bb82e2029b2ff2d02fa426 to your computer and use it in GitHub Desktop.
Frontal Surface Area STL
package main
import (
"bufio"
"fmt"
"math"
"os"
"strings"
)
func calculateTriangleArea(v1, v2, v3 [3]float64) float64 {
a := math.Sqrt(math.Pow(v2[0]-v1[0], 2) + math.Pow(v2[1]-v1[1], 2) + math.Pow(v2[2]-v1[2], 2))
b := math.Sqrt(math.Pow(v3[0]-v2[0], 2) + math.Pow(v3[1]-v2[1], 2) + math.Pow(v3[2]-v2[2], 2))
c := math.Sqrt(math.Pow(v1[0]-v3[0], 2) + math.Pow(v1[1]-v3[1], 2) + math.Pow(v1[2]-v3[2], 2))
s := (a + b + c) / 2
return math.Sqrt(s * (s - a) * (s - b) * (s - c))
}
var (
// Z-axis (default)
directionZ = [3]float64{0, 0, 1}
// Y-axis
directionY = [3]float64{0, 1, 0}
// X-axis
directionX = [3]float64{1, 0, 0}
// Define a threshold angle (in radians) to determine if a triangle is frontal
//
// 45 degrees
thresholdAngle = math.Pi / 4.0
)
func isFrontalTriangle(normal, incomingAirflowDirection [3]float64) bool {
// Calculate the angle between the normal vector and the incoming (airflow) direction
angle := math.Acos(normal[0]*incomingAirflowDirection[0] + normal[1]*incomingAirflowDirection[1] + normal[2]*incomingAirflowDirection[2])
return angle <= thresholdAngle
}
func main() {
if os.Args[1] == "-h" || os.Args[1] == "--help" {
fmt.Println("Usage: go run main.go [path_to_your_stl_file.stl]")
return
}
filePath := os.Args[1]
if !strings.HasSuffix(filePath, ".stl") {
fmt.Println("Error: The file must be an STL file (and end with '.stl').")
return
}
frontalArea := 0.0
file, err := os.Open(filePath)
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer file.Close()
var (
v1, v2, v3 [3]float64
normal [3]float64
)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
// Identify facet normal lines
if strings.HasPrefix(line, "facet normal") {
// Extract the normal vector
_, err := fmt.Sscanf(line, "facet normal %f %f %f", &normal[0], &normal[1], &normal[2])
if err != nil {
fmt.Printf("Error reading normal vector %q: %v\n", line, err)
return
}
if isFrontalTriangle(normal, directionZ) {
// Identify vertex lines
for i := 0; i < 3; i++ {
scanner.Scan()
line := strings.TrimSpace(scanner.Text())
// Extract the vertex coordinates
var x, y, z float64
_, err := fmt.Sscanf(line, "vertex %f %f %f", &x, &y, &z)
if err != nil {
fmt.Printf("Error reading vertex %q: %v\n", line, err)
return
}
switch i {
case 0:
v1 = [3]float64{x, y, z}
case 1:
v2 = [3]float64{x, y, z}
case 2:
v3 = [3]float64{x, y, z}
}
}
triangleArea := calculateTriangleArea(v1, v2, v3)
frontalArea += triangleArea
} else {
// discard the next 3 lines
for i := 0; i < 3; i++ {
scanner.Scan()
}
}
}
}
if err := scanner.Err(); err != nil {
fmt.Println("Error reading file:", err)
return
}
fmt.Printf("Frontal Area: %.6f\n", frontalArea)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment