mathtools/cmd/shoelace.go

117 lines
2.8 KiB
Go
Raw Normal View History

2025-09-09 03:15:53 +00:00
/*
Copyright © 2025 filifa
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cmd
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
"github.com/spf13/cobra"
2025-09-30 01:52:52 +00:00
"scm.dairydemon.net/filifa/mathtools/internal/lib"
2025-09-09 03:15:53 +00:00
)
var shoelaceFile string
func splitLines(file *os.File) []string {
slice := make([]string, 0)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
slice = append(slice, scanner.Text())
}
return slice
}
2025-09-30 01:52:52 +00:00
func readFromFile(filepath string) ([]lib.Point, error) {
points := make([]lib.Point, 0)
2025-09-09 03:15:53 +00:00
file, err := os.Open(filepath)
if err != nil {
return points, err
}
defer file.Close()
lines := splitLines(file)
for _, line := range lines {
fields := strings.Fields(line)
x, err := strconv.ParseFloat(fields[0], 64)
if err != nil {
return points, err
}
y, err := strconv.ParseFloat(fields[1], 64)
if err != nil {
return points, err
}
2025-09-30 01:52:52 +00:00
points = append(points, lib.Point{x, y})
2025-09-09 03:15:53 +00:00
}
return points, nil
}
func shoelace(cmd *cobra.Command, args []string) {
2025-09-30 01:52:52 +00:00
var coordinates []lib.Point
2025-09-09 03:15:53 +00:00
var err error
if shoelaceFile != "" {
coordinates, err = readFromFile(shoelaceFile)
if err != nil {
cobra.CheckErr(err)
}
} else {
cobra.CheckErr("filename required")
}
2025-09-30 01:52:52 +00:00
fmt.Println(lib.Area(coordinates))
2025-09-09 03:15:53 +00:00
}
// shoelaceCmd represents the shoelace command
var shoelaceCmd = &cobra.Command{
2025-09-18 01:02:05 +00:00
Use: "shoelace -f FILE",
2025-09-09 03:15:53 +00:00
Short: "Compute the area of a simple polygon from the vertex coordinates",
2025-09-18 01:02:05 +00:00
Long: `Compute the area of a simple polygon from the vertex coordinates.
Put each point on its own line, with each coordinate separated by whitespace. For example, a file with
1 6
3 1
7 2
4 4
8 5
will output an area of 16.5.`,
Run: shoelace,
2025-09-09 03:15:53 +00:00
}
func init() {
rootCmd.AddCommand(shoelaceCmd)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// shoelaceCmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// shoelaceCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
shoelaceCmd.Flags().StringVarP(&shoelaceFile, "file", "f", "", "file with coordinates")
// TODO: add flag for inputting coordinates from cli
}