判斷一個點是否在三角形內部【Golang實現】

【題目】

在二維座標系中,所有的值都是double類型,那麼一個三角形可以由3個點來代表,給定3個點代表的三角形,再給定一個點(x ,y ),判斷(x ,y )是否在三角形中。

解決方案

方案一:基於面積

package main

import (
	"fmt"
	"math"
)

type Point struct {
	x float64
	y float64
}

type Triangle struct {
	p1, p2, p3 Point
}

func (t *Triangle) IsInside(p Point) bool {
	area1 := getArea(t.p1, t.p2, p)
	area2 := getArea(t.p1, t.p3, p)
	area3 := getArea(t.p2, t.p3, p)
	areaAll := getArea(t.p1, t.p2, t.p3)
	fmt.Println(area1, area2, area3, areaAll)
	return areaAll >= (area1 + area2 + area3)
}

// 計算兩點的距離
func getSideLength(p1, p2 Point) float64 {
	a := math.Abs(p1.x - p2.x)
	b := math.Abs(p1.y - p2.y)
	return math.Sqrt(a*a + b*b)
}

// 根據三點座標計算三角形面積(海倫公式)
func getArea(p1, p2, p3 Point) float64 {
	side1Len := getSideLength(p1, p2)
	side2Len := getSideLength(p1, p3)
	side3Len := getSideLength(p2, p3)
	p := (side1Len + side2Len + side3Len) / 2
	return math.Sqrt((p - side1Len) * (p - side2Len) * (p - side3Len) * p)
}

func main() {
	t := Triangle{Point{0, 100}, Point{0, 0}, Point{100, 0}}
	p := Point{2, 2}
	if t.IsInside(p) {
		fmt.Println(p, "在", t)
	} else {
		fmt.Println(p, "不在", t)

	}
}

方案二:基於矢量叉乘運算

package main

import (
	"fmt"
)

type Point struct {
	x float64
	y float64
}

type Triangle struct {
	p1, p2, p3 Point
}

// 最好切換成複數計算
func crossProduct(x1, y1, x2, y2 float64) float64 {
	// 向量(x 1,y 1)叉乘向量(x 2,y 2)
	return x1*y2 - y1*x2
}

func (t *Triangle) IsInside(p Point) bool {
	// 調整順序
	if crossProduct(t.p3.x-t.p1.x, t.p3.y-t.p1.y,
		t.p2.x-t.p1.x, t.p2.y-t.p1.y) >= 0 {
		t.p2.x, t.p2.y, t.p3.x, t.p3.y = t.p3.x, t.p3.y, t.p2.x, t.p2.y
	}
	// switch
	if crossProduct(t.p2.x-t.p1.x, t.p2.y-t.p1.y,
		p.x-t.p1.x, p.y-t.p1.y) < 0 ||
		crossProduct(t.p3.x-t.p2.x, t.p3.y-t.p2.y,
			p.x-t.p2.x-p.x, p.y-t.p2.y) < 0 ||
		crossProduct(t.p1.x-t.p3.x, t.p1.y-t.p3.y,
			p.x-t.p3.x, p.y-t.p3.y) < 0 {
		return false
	}

	return true
}

func main() {
	rect := Triangle{Point{0, 100}, Point{0, 0}, Point{100, 0}}
	p := Point{1, 200}
	if rect.IsInside(p) {
		fmt.Println(p, "在", rect)
	} else {
		fmt.Println(p, "不在", rect)

	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章