From f5daf337a9c25f3354aa2cf8e7b072ae39291270 Mon Sep 17 00:00:00 2001 From: Maximilian Friedersdorff Date: Mon, 11 Mar 2019 19:17:04 +0000 Subject: [PATCH 1/1] Solution for problem 102: Triangle containment --- 102_triangle_containment/main.go | 94 ++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 102_triangle_containment/main.go diff --git a/102_triangle_containment/main.go b/102_triangle_containment/main.go new file mode 100644 index 0000000..7a2d4b6 --- /dev/null +++ b/102_triangle_containment/main.go @@ -0,0 +1,94 @@ +package main + +import ( + "encoding/csv" + "errors" + "fmt" + "git.friedersdorff.com/max/vector.go" + "os" + "strconv" +) + +// sameSide returns true if p1 and p2 are on the same side of the line ab, false +// otherwise +func sameSide(p1, p2, a, b vector.Vec) bool { + cp1 := b.Sub(a).Cross(p1.Sub(a)) + cp2 := b.Sub(a).Cross(p2.Sub(a)) + + return cp1.Dot(cp2) >= 0 +} + +// inTriangle returns true if point p is in triangle abc, false otherwise +func inTriangle(p, a, b, c vector.Vec) bool { + return sameSide(p, a, b, c) && sameSide(p, b, a, c) && sameSide(p, c, a, b) +} + +func getVec(record []string) ([]vector.Vec, error) { + if len(record)%2 != 0 { + return nil, errors.New( + fmt.Sprintf("Length of record is not divisible by 2: %s", + len(record))) + } + var vecs []vector.Vec + + floats := make([]float64, len(record)) + for i, v := range record { + num, err := strconv.ParseFloat(v, 64) + + if err != nil { + return nil, errors.New( + fmt.Sprintf("Couldn't parse record to floats: %s", + record)) + } + + floats[i] = num + } + + for i := 0; i < len(floats); i += 2 { + vecs = append(vecs, vector.Vec{floats[i], floats[i+1], 0.0}) + } + return vecs, nil + +} + +func main() { + if len(os.Args) != 2 { + fmt.Println("Expect input file as first argument.") + return + } + + f, err := os.Open(os.Args[1]) + + if err != nil { + fmt.Println(err) + return + } + + r := csv.NewReader(f) + + nInTriangle := 0 + for { + triangle, err := r.Read() + if err != nil { + break + } + + points, err := getVec(triangle) + if err != nil { + + break + } + + if len(points) != 3 { + break + } + + if inTriangle(vector.Vec{0, 0, 0}, + points[0], points[1], points[2]) { + nInTriangle++ + } + } + + fmt.Println(nInTriangle) + return +} -- 2.47.1