判斷兩三角形是否相交

1,原理:在上篇文章中我們可以判斷點是否在三角形內。這張判斷兩三角形是否相交,只需要判斷三角形A的三個頂點不在三角形B內,三角形B的三個頂點不在三角形A則滿足兩三角形相離,並且判斷三角形A的三條邊與三角形B 都不想交

代碼如下:

// test project main.go
package main

import (
	"fmt"
)

//座標
type victor struct {
	X float32
	Y float32
}

func main() {
	//測試點
	pA1 := &victor{0, 0}
	pA2 := &victor{2, 0}
	pA3 := &victor{2, 2}
	pB1 := &victor{1.5, -1}
	pB2 := &victor{0, 1}
	pB3 := &victor{1.5, 2}
	IsCorssTriangle(pA1, pA2, pA3, pB1, pB2, pB3)

}

//判線段是否在三角形內
func IsCorssTriangle(pA1 *victor, pA2 *victor, pA3 *victor, pB1 *victor, pB2 *victor, pB3 *victor) bool {
	//比例係數(p1.X - p2.X) / (p1.Y - p2.Y)
	//C p1.Y-((p1.X - p2.X) / (p1.Y - p2.Y))*p1.X
	//IsTriangle判斷是否是三角形
	if !IsTriangle(pA1, pA2, pA3) {
		fmt.Println("該三點不能組成三角形")
		return false
	}
	//IsTriangle判斷是否是三角形
	if !IsTriangle(pB1, pB2, pB3) {
		fmt.Println("該三點不能組成三角形")
		return false
	}
	//A三角形三點如果全部在B的外面   並且B的三點全部在A的外面  滿足這個條件三角形必定不相交 true 是相交 false 不相交
	if IsInTriangle(pA1, pA2, pA3, pB1) && IsInTriangle(pA1, pA2, pA3, pB2) && IsInTriangle(pA1, pA2, pA3, pB3) && IsInTriangle(pB1, pB2, pB3, pA1) && IsInTriangle(pB1, pB2, pB3, pA3) && IsInTriangle(pB1, pB2, pB3, pA2) {
		fmt.Println("相交了哦")
		return true
	}
	//A三角的三條直線是否和B三角形相交
	if IsCorssDirec(pA1, pA2, pB1, pB2) || IsCorssDirec(pA1, pA2, pB1, pB3) || IsCorssDirec(pA1, pA2, pB2, pB2) {
		fmt.Println("相交了哦")
		return true
	}
	if IsCorssDirec(pA1, pA3, pB1, pB2) || IsCorssDirec(pA1, pA3, pB1, pB3) || IsCorssDirec(pA1, pA3, pB2, pB2) {
		fmt.Println("相交了哦")
		return true
	}
	if IsCorssDirec(pA3, pA2, pB1, pB2) || IsCorssDirec(pA3, pA2, pB1, pB3) || IsCorssDirec(pA3, pA2, pB2, pB2) {
		fmt.Println("相交了哦")
		return true
	}
	fmt.Println("兩三角形不想交")
	return false
}

//判斷兩條直線是否相交 true 是相交 false 不相交
func IsCorssDirec(pA1 *victor, pA2 *victor, pB1 *victor, pB2 *victor) bool {
	if GetMinger(pA1.X, pA2.X) > GetBigger(pB1.X, pB2.X) {
		return false
	}
	if GetMinger(pA1.Y, pA2.Y) > GetBigger(pB1.Y, pB2.Y) {
		return false
	}
	if GetBigger(pA1.Y, pA2.Y) < GetMinger(pB1.Y, pB2.Y) {
		return false
	}
	if GetBigger(pA1.X, pA2.X) < GetMinger(pB1.X, pB2.X) {
		return false
	}
	if mult(pB1, pA2, pA1)*mult(pA2, pB2, pA1) < 0 {
		return false
	}
	if mult(pA1, pB2, pB1)*mult(pB2, pA2, pB1) < 0 {
		return false
	}
	return true
}

//叉積
func mult(a *victor, b *victor, c *victor) float32 {
	return (a.X-c.X)*(b.Y-c.Y) - (b.X-c.X)*(a.Y-c.Y)
}

//獲取大數字
func GetBigger(a, b float32) float32 {
	if a > b {
		return a
	} else {
		return b
	}
}

//獲取大數字
func GetMinger(a, b float32) float32 {
	if a > b {
		return b
	} else {
		return a
	}
}

//判斷點是否在三角形內
func IsInTriangle(p1 *victor, p2 *victor, p3 *victor, p *victor) bool {
	//IsTriangle判斷是否是三角形
	if !IsTriangle(p1, p2, p3) {
		fmt.Println("該三點不能組成三角形")
		return false
	}
	//判斷點是否在三角形的三條邊同側
	if IsSameDirec(p1, p2, p3, p) && IsSameDirec(p1, p3, p2, p) && IsSameDirec(p3, p2, p1, p) {
		fmt.Println("點在三角形裏面")
		return true
	} else {
		fmt.Println("在三角形外面")
		return false
	}

}

//判斷是否是三角形
//p1,p2,p3分別爲三個頂點座標
func IsTriangle(p1 *victor, p2 *victor, p3 *victor) bool {
	//是否三點X座標相同
	if p1.X == p2.X && p1.X == p3.X {
		return false
	}
	//是否三點Y座標相同
	if p1.Y == p2.Y && p1.Y == p3.Y {
		return false
	}
	return true
}

//求第三點與另外兩點直線是否同側
//p1,p2 爲三角形的兩頂點
//p爲測試點
func IsSameDirec(p1 *victor, p2 *victor, p3 *victor, p *victor) bool {
	//比例係數(p1.X - p2.X) / (p1.Y - p2.Y)
	//C p1.Y-((p1.X - p2.X) / (p1.Y - p2.Y))*p1.X
	var tag bool

	//如果 p1.X=p2.X則此時與Y軸平行,只需要比較X
	if p1.X == p2.X {
		if (p3.X >= p1.X && p.X >= p1.X) || (p3.X < p1.X && p.X < p1.X) {
			return true
		} else {
			return false
		}
	} else {
		//如果P3在直線上面就爲true
		if p3.Y >= (p1.Y-p2.Y)/(p1.X-p2.X)*p3.X+p1.Y-((p1.Y-p2.Y)/(p1.X-p2.X))*p1.X {
			tag = true
		} else {
			tag = false
		}
		if tag {
			if p.Y >= (p1.Y-p2.Y)/(p1.X-p2.X)*p.X+p1.Y-((p1.Y-p2.Y)/(p1.X-p2.X))*p1.X {
				return true
			}
		} else {
			if p.Y < (p1.Y-p2.Y)/(p1.X-p2.X)*p.X+p1.Y-((p1.Y-p2.Y)/(p1.X-p2.X))*p1.X {
				return true
			}
		}
		return false
	}
}


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