Removed redundant collision related codes.

This commit is contained in:
genxium 2023-02-26 20:39:30 +08:00
parent b9827f8430
commit e213fdfb04
6 changed files with 6 additions and 616 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,164 +0,0 @@
// This file contains code from the gonum repository:
// https://github.com/gonum/gonum/blob/master/internal/asm/f64/scalunitaryto_amd64.s
// it is distributed under the 3-Clause BSD license:
//
// Copyright ©2013 The Gonum Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Gonum project nor the names of its authors and
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Some of the loop unrolling code is copied from:
// http://golang.org/src/math/big/arith_amd64.s
// which is distributed under these terms:
//
// Copyright (c) 2012 The Go Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// +build !noasm
#include "textflag.h"
#define X_PTR SI
#define Y_PTR DX
#define DST_PTR DI
#define IDX AX
#define LEN CX
#define TAIL BX
#define ALPHA X0
#define ALPHA_2 X1
// func axpyUnitaryTo(dst []float64, alpha float64, x, y []float64)
TEXT ·axpyUnitaryTo(SB), NOSPLIT, $0
MOVQ dst_base+0(FP), DST_PTR // DST_PTR := &dst
MOVQ x_base+32(FP), X_PTR // X_PTR := &x
MOVQ y_base+56(FP), Y_PTR // Y_PTR := &y
MOVQ x_len+40(FP), LEN // LEN = min( len(x), len(y), len(dst) )
CMPQ y_len+64(FP), LEN
CMOVQLE y_len+64(FP), LEN
CMPQ dst_len+8(FP), LEN
CMOVQLE dst_len+8(FP), LEN
CMPQ LEN, $0
JE end // if LEN == 0 { return }
XORQ IDX, IDX // IDX = 0
MOVSD alpha+24(FP), ALPHA
SHUFPD $0, ALPHA, ALPHA // ALPHA := { alpha, alpha }
MOVQ Y_PTR, TAIL // Check memory alignment
ANDQ $15, TAIL // TAIL = &y % 16
JZ no_trim // if TAIL == 0 { goto no_trim }
// Align on 16-byte boundary
MOVSD (X_PTR), X2 // X2 := x[0]
MULSD ALPHA, X2 // X2 *= a
ADDSD (Y_PTR), X2 // X2 += y[0]
MOVSD X2, (DST_PTR) // y[0] = X2
INCQ IDX // i++
DECQ LEN // LEN--
JZ end // if LEN == 0 { return }
no_trim:
MOVQ LEN, TAIL
ANDQ $7, TAIL // TAIL := n % 8
SHRQ $3, LEN // LEN = floor( n / 8 )
JZ tail_start // if LEN == 0 { goto tail_start }
MOVUPS ALPHA, ALPHA_2 // ALPHA_2 := ALPHA for pipelining
loop: // do {
// y[i] += alpha * x[i] unrolled 8x.
MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i]
MOVUPS 16(X_PTR)(IDX*8), X3
MOVUPS 32(X_PTR)(IDX*8), X4
MOVUPS 48(X_PTR)(IDX*8), X5
MULPD ALPHA, X2 // X_i *= alpha
MULPD ALPHA_2, X3
MULPD ALPHA, X4
MULPD ALPHA_2, X5
ADDPD (Y_PTR)(IDX*8), X2 // X_i += y[i]
ADDPD 16(Y_PTR)(IDX*8), X3
ADDPD 32(Y_PTR)(IDX*8), X4
ADDPD 48(Y_PTR)(IDX*8), X5
MOVUPS X2, (DST_PTR)(IDX*8) // y[i] = X_i
MOVUPS X3, 16(DST_PTR)(IDX*8)
MOVUPS X4, 32(DST_PTR)(IDX*8)
MOVUPS X5, 48(DST_PTR)(IDX*8)
ADDQ $8, IDX // i += 8
DECQ LEN
JNZ loop // } while --LEN > 0
CMPQ TAIL, $0 // if TAIL == 0 { return }
JE end
tail_start: // Reset loop registers
MOVQ TAIL, LEN // Loop counter: LEN = TAIL
SHRQ $1, LEN // LEN = floor( TAIL / 2 )
JZ tail_one // if LEN == 0 { goto tail }
tail_two: // do {
MOVUPS (X_PTR)(IDX*8), X2 // X2 = x[i]
MULPD ALPHA, X2 // X2 *= alpha
ADDPD (Y_PTR)(IDX*8), X2 // X2 += y[i]
MOVUPS X2, (DST_PTR)(IDX*8) // y[i] = X2
ADDQ $2, IDX // i += 2
DECQ LEN
JNZ tail_two // } while --LEN > 0
ANDQ $1, TAIL
JZ end // if TAIL == 0 { goto end }
tail_one:
MOVSD (X_PTR)(IDX*8), X2 // X2 = x[i]
MULSD ALPHA, X2 // X2 *= a
ADDSD (Y_PTR)(IDX*8), X2 // X2 += y[i]
MOVSD X2, (DST_PTR)(IDX*8) // y[i] = X2
end:
RET

View File

@ -1,137 +0,0 @@
// This file contains code from the gonum repository:
// https://github.com/gonum/gonum/blob/master/internal/asm/f64/axpyunitaryto_amd64.s
// it is distributed under the 3-Clause BSD license:
//
// Copyright ©2013 The Gonum Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Gonum project nor the names of its authors and
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Some of the loop unrolling code is copied from:
// http://golang.org/src/math/big/arith_amd64.s
// which is distributed under these terms:
//
// Copyright (c) 2012 The Go Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// +build !noasm
#include "textflag.h"
#define MOVDDUP_ALPHA LONG $0x44120FF2; WORD $0x2024 // @ MOVDDUP 32(SP), X0 /*XMM0, 32[RSP]*/
#define X_PTR SI
#define DST_PTR DI
#define IDX AX
#define LEN CX
#define TAIL BX
#define ALPHA X0
#define ALPHA_2 X1
// func scalUnitaryTo(dst []float64, alpha float64, x []float64)
// This function assumes len(dst) >= len(x).
TEXT ·scalUnitaryTo(SB), NOSPLIT, $0
MOVQ x_base+32(FP), X_PTR // X_PTR = &x
MOVQ dst_base+0(FP), DST_PTR // DST_PTR = &dst
MOVDDUP_ALPHA // ALPHA = { alpha, alpha }
MOVQ x_len+40(FP), LEN // LEN = len(x)
CMPQ LEN, $0
JE end // if LEN == 0 { return }
XORQ IDX, IDX // IDX = 0
MOVQ LEN, TAIL
ANDQ $7, TAIL // TAIL = LEN % 8
SHRQ $3, LEN // LEN = floor( LEN / 8 )
JZ tail_start // if LEN == 0 { goto tail_start }
MOVUPS ALPHA, ALPHA_2 // ALPHA_2 = ALPHA for pipelining
loop: // do { // dst[i] = alpha * x[i] unrolled 8x.
MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i]
MOVUPS 16(X_PTR)(IDX*8), X3
MOVUPS 32(X_PTR)(IDX*8), X4
MOVUPS 48(X_PTR)(IDX*8), X5
MULPD ALPHA, X2 // X_i *= ALPHA
MULPD ALPHA_2, X3
MULPD ALPHA, X4
MULPD ALPHA_2, X5
MOVUPS X2, (DST_PTR)(IDX*8) // dst[i] = X_i
MOVUPS X3, 16(DST_PTR)(IDX*8)
MOVUPS X4, 32(DST_PTR)(IDX*8)
MOVUPS X5, 48(DST_PTR)(IDX*8)
ADDQ $8, IDX // i += 8
DECQ LEN
JNZ loop // while --LEN > 0
CMPQ TAIL, $0
JE end // if TAIL == 0 { return }
tail_start: // Reset loop counters
MOVQ TAIL, LEN // Loop counter: LEN = TAIL
SHRQ $1, LEN // LEN = floor( TAIL / 2 )
JZ tail_one // if LEN == 0 { goto tail_one }
tail_two: // do {
MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i]
MULPD ALPHA, X2 // X_i *= ALPHA
MOVUPS X2, (DST_PTR)(IDX*8) // dst[i] = X_i
ADDQ $2, IDX // i += 2
DECQ LEN
JNZ tail_two // while --LEN > 0
ANDQ $1, TAIL
JZ end // if TAIL == 0 { return }
tail_one:
MOVSD (X_PTR)(IDX*8), X2 // X_i = x[i]
MULSD ALPHA, X2 // X_i *= ALPHA
MOVSD X2, (DST_PTR)(IDX*8) // dst[i] = X_i
end:
RET

View File

@ -1,9 +0,0 @@
//go:build !noasm
// +build !noasm
package resolv
// functions from the gonum package that optimizes arithmetic
// operations on lists of float64 values
func axpyUnitaryTo(dst []float64, alpha float64, x, y []float64)
func scalUnitaryTo(dst []float64, alpha float64, x []float64)

View File

@ -33,20 +33,12 @@ func NewLine(x, y, x2, y2 float64) *Line {
} }
} }
func (line *Line) Project(axis Vector) Vector {
return line.Vector().Scale(axis.Dot(line.Start.Sub(line.End)))
}
func (line *Line) Normal() Vector { func (line *Line) Normal() Vector {
dy := line.End[1] - line.Start[1] dy := line.End[1] - line.Start[1]
dx := line.End[0] - line.Start[0] dx := line.End[0] - line.Start[0]
return Vector{dy, -dx}.Unit() return Vector{dy, -dx}.Unit()
} }
func (line *Line) Vector() Vector {
return line.End.Clone().Sub(line.Start).Unit()
}
// IntersectionPointsLine returns the intersection point of a Line with another Line as a Vector. If no intersection is found, it will return nil. // IntersectionPointsLine returns the intersection point of a Line with another Line as a Vector. If no intersection is found, it will return nil.
func (line *Line) IntersectionPointsLine(other *Line) Vector { func (line *Line) IntersectionPointsLine(other *Line) Vector {
@ -79,51 +71,6 @@ func (line *Line) IntersectionPointsLine(other *Line) Vector {
} }
// IntersectionPointsCircle returns a slice of Vectors, each indicating the intersection point. If no intersection is found, it will return an empty slice.
func (line *Line) IntersectionPointsCircle(circle *Circle) []Vector {
points := []Vector{}
cp := Vector{circle.X, circle.Y}
lStart := line.Start.Sub(cp)
lEnd := line.End.Sub(cp)
diff := lEnd.Sub(lStart)
a := diff[0]*diff[0] + diff[1]*diff[1]
b := 2 * ((diff[0] * lStart[0]) + (diff[1] * lStart[1]))
c := (lStart[0] * lStart[0]) + (lStart[1] * lStart[1]) - (circle.Radius * circle.Radius)
det := b*b - (4 * a * c)
if det < 0 {
// Do nothing, no intersections
} else if det == 0 {
t := -b / (2 * a)
if t >= 0 && t <= 1 {
points = append(points, Vector{line.Start[0] + t*diff[0], line.Start[1] + t*diff[1]})
}
} else {
t := (-b + math.Sqrt(det)) / (2 * a)
// We have to ensure t is between 0 and 1; otherwise, the collision points are on the circle as though the lines were infinite in length.
if t >= 0 && t <= 1 {
points = append(points, Vector{line.Start[0] + t*diff[0], line.Start[1] + t*diff[1]})
}
t = (-b - math.Sqrt(det)) / (2 * a)
if t >= 0 && t <= 1 {
points = append(points, Vector{line.Start[0] + t*diff[0], line.Start[1] + t*diff[1]})
}
}
return points
}
type ConvexPolygon struct { type ConvexPolygon struct {
Points *RingBuffer Points *RingBuffer
X, Y float64 X, Y float64
@ -294,24 +241,6 @@ func (cp *ConvexPolygon) MoveVec(vec Vector) {
cp.Y += vec.Y() cp.Y += vec.Y()
} }
// Center returns the transformed Center of the ConvexPolygon.
func (cp *ConvexPolygon) Center() Vector {
pos := Vector{0, 0}
vertices := cp.Transformed()
for _, v := range vertices {
pos.Add(v)
}
denom := float64(len(vertices))
pos[0] /= denom
pos[1] /= denom
return pos
}
// Project projects (i.e. flattens) the ConvexPolygon onto the provided axis. // Project projects (i.e. flattens) the ConvexPolygon onto the provided axis.
func (cp *ConvexPolygon) Project(axis Vector) Projection { func (cp *ConvexPolygon) Project(axis Vector) Projection {
axis = axis.Unit() axis = axis.Unit()
@ -453,13 +382,7 @@ func (cp *ConvexPolygon) Intersection(dx, dy float64, other Shape) *ContactSet {
cp.X += dx cp.X += dx
cp.Y += dy cp.Y += dy
if circle, isCircle := other.(*Circle); isCircle { if poly, isPoly := other.(*ConvexPolygon); isPoly {
for _, line := range cp.Lines() {
contactSet.Points = append(contactSet.Points, line.IntersectionPointsCircle(circle)...)
}
} else if poly, isPoly := other.(*ConvexPolygon); isPoly {
for _, line := range cp.Lines() { for _, line := range cp.Lines() {
@ -476,29 +399,11 @@ func (cp *ConvexPolygon) Intersection(dx, dy float64, other Shape) *ContactSet {
} }
if len(contactSet.Points) > 0 { if len(contactSet.Points) > 0 {
// Do nothing
for _, point := range contactSet.Points {
contactSet.Center = contactSet.Center.Add(point)
}
contactSet.Center[0] /= float64(len(contactSet.Points))
contactSet.Center[1] /= float64(len(contactSet.Points))
if mtv := cp.calculateMTV(contactSet, other); mtv != nil {
contactSet.MTV = mtv
}
} else { } else {
contactSet = nil contactSet = nil
} }
// If dx or dy aren't 0, then the MTV will be greater to compensate; this adjusts the vector back.
if contactSet != nil && (dx != 0 || dy != 0) {
deltaMagnitude := Vector{dx, dy}.Magnitude()
ogMagnitude := contactSet.MTV.Magnitude()
contactSet.MTV = contactSet.MTV.Unit().Scale(ogMagnitude - deltaMagnitude)
}
cp.X = ogX cp.X = ogX
cp.Y = ogY cp.Y = ogY
@ -506,76 +411,6 @@ func (cp *ConvexPolygon) Intersection(dx, dy float64, other Shape) *ContactSet {
} }
// calculateMTV returns the MTV, if possible, and a bool indicating whether it was possible or not.
func (cp *ConvexPolygon) calculateMTV(contactSet *ContactSet, otherShape Shape) Vector {
delta := Vector{0, 0}
smallest := Vector{math.MaxFloat64, 0}
switch other := otherShape.(type) {
case *ConvexPolygon:
for _, axis := range cp.SATAxes() {
if !cp.Project(axis).Overlapping(other.Project(axis)) {
return nil
}
overlap := cp.Project(axis).Overlap(other.Project(axis))
if smallest.Magnitude() > overlap {
smallest = axis.Scale(overlap)
}
}
for _, axis := range other.SATAxes() {
if !cp.Project(axis).Overlapping(other.Project(axis)) {
return nil
}
overlap := cp.Project(axis).Overlap(other.Project(axis))
if smallest.Magnitude() > overlap {
smallest = axis.Scale(overlap)
}
}
// Removed support of "Circle" to remove dependency of "sort" module
}
delta[0] = smallest[0]
delta[1] = smallest[1]
return delta
}
// ContainedBy returns if the ConvexPolygon is wholly contained by the other shape provided.
func (cp *ConvexPolygon) ContainedBy(otherShape Shape) bool {
switch other := otherShape.(type) {
case *ConvexPolygon:
for _, axis := range cp.SATAxes() {
if !cp.Project(axis).IsInside(other.Project(axis)) {
return false
}
}
for _, axis := range other.SATAxes() {
if !cp.Project(axis).IsInside(other.Project(axis)) {
return false
}
}
}
return true
}
// NewRectangle returns a rectangular ConvexPolygon with the vertices in clockwise order. In actuality, an AABBRectangle should be its own // NewRectangle returns a rectangular ConvexPolygon with the vertices in clockwise order. In actuality, an AABBRectangle should be its own
// "thing" with its own optimized Intersection code check. // "thing" with its own optimized Intersection code check.
func NewRectangle(x, y, w, h float64) *ConvexPolygon { func NewRectangle(x, y, w, h float64) *ConvexPolygon {
@ -587,143 +422,6 @@ func NewRectangle(x, y, w, h float64) *ConvexPolygon {
) )
} }
type Circle struct {
X, Y, Radius float64
}
// NewCircle returns a new Circle, with its center at the X and Y position given, and with the defined radius.
func NewCircle(x, y, radius float64) *Circle {
circle := &Circle{
X: x,
Y: y,
Radius: radius,
}
return circle
}
func (circle *Circle) Clone() Shape {
return NewCircle(circle.X, circle.Y, circle.Radius)
}
// Bounds returns the top-left and bottom-right corners of the Circle.
func (circle *Circle) Bounds() (Vector, Vector) {
return Vector{circle.X - circle.Radius, circle.Y - circle.Radius}, Vector{circle.X + circle.Radius, circle.Y + circle.Radius}
}
// Intersection tests to see if a Circle intersects with the other given Shape. dx and dy are delta movement variables indicating
// movement to be applied before the intersection check (thereby allowing you to see if a Shape would collide with another if it
// were in a different relative location). If an Intersection is found, a ContactSet will be returned, giving information regarding
// the intersection.
func (circle *Circle) Intersection(dx, dy float64, other Shape) *ContactSet {
var contactSet *ContactSet
ox := circle.X
oy := circle.Y
circle.X += dx
circle.Y += dy
// here
switch shape := other.(type) {
case *ConvexPolygon:
// Maybe this would work?
contactSet = shape.Intersection(-dx, -dy, circle)
if contactSet != nil {
contactSet.MTV = contactSet.MTV.Scale(-1)
}
case *Circle:
contactSet = NewContactSet()
contactSet.Points = circle.IntersectionPointsCircle(shape)
if len(contactSet.Points) == 0 {
return nil
}
contactSet.MTV = Vector{circle.X - shape.X, circle.Y - shape.Y}
dist := contactSet.MTV.Magnitude()
contactSet.MTV = contactSet.MTV.Unit().Scale(circle.Radius + shape.Radius - dist)
for _, point := range contactSet.Points {
contactSet.Center = contactSet.Center.Add(point)
}
contactSet.Center[0] /= float64(len(contactSet.Points))
contactSet.Center[1] /= float64(len(contactSet.Points))
// if contactSet != nil {
// contactSet.MTV[0] -= dx
// contactSet.MTV[1] -= dy
// }
// contactSet.MTV = Vector{circle.X - shape.X, circle.Y - shape.Y}
}
circle.X = ox
circle.Y = oy
return contactSet
}
// Move translates the Circle by the designated X and Y values.
func (circle *Circle) Move(x, y float64) {
circle.X += x
circle.Y += y
}
// MoveVec translates the Circle by the designated Vector.
func (circle *Circle) MoveVec(vec Vector) {
circle.X += vec.X()
circle.Y += vec.Y()
}
// SetPosition sets the center position of the Circle using the X and Y values given.
func (circle *Circle) SetPosition(x, y float64) {
circle.X = x
circle.Y = y
}
// SetPosition sets the center position of the Circle using the Vector given.
func (circle *Circle) SetPositionVec(vec Vector) {
circle.X = vec.X()
circle.Y = vec.Y()
}
// Position() returns the X and Y position of the Circle.
func (circle *Circle) Position() (float64, float64) {
return circle.X, circle.Y
}
// PointInside returns if the given Vector is inside of the circle.
func (circle *Circle) PointInside(point Vector) bool {
return point.Sub(Vector{circle.X, circle.Y}).Magnitude() <= circle.Radius
}
// IntersectionPointsCircle returns the intersection points of the two circles provided.
func (circle *Circle) IntersectionPointsCircle(other *Circle) []Vector {
d := math.Sqrt(math.Pow(other.X-circle.X, 2) + math.Pow(other.Y-circle.Y, 2))
if d > circle.Radius+other.Radius || d < math.Abs(circle.Radius-other.Radius) || d == 0 && circle.Radius == other.Radius {
return nil
}
a := (math.Pow(circle.Radius, 2) - math.Pow(other.Radius, 2) + math.Pow(d, 2)) / (2 * d)
h := math.Sqrt(math.Pow(circle.Radius, 2) - math.Pow(a, 2))
x2 := circle.X + a*(other.X-circle.X)/d
y2 := circle.Y + a*(other.Y-circle.Y)/d
return []Vector{
{x2 + h*(other.Y-circle.Y)/d, y2 - h*(other.X-circle.X)/d},
{x2 - h*(other.Y-circle.Y)/d, y2 + h*(other.X-circle.X)/d},
}
}
type Projection struct { type Projection struct {
Min, Max float64 Min, Max float64
} }

View File

@ -31,6 +31,7 @@ func (v Vector) Clone() Vector {
return clone return clone
} }
/*
// Add a vector with a vector or a set of vectors // Add a vector with a vector or a set of vectors
func Add(v1 Vector, vs ...Vector) Vector { func Add(v1 Vector, vs ...Vector) Vector {
return v1.Clone().Add(vs...) return v1.Clone().Add(vs...)
@ -81,6 +82,7 @@ func (v Vector) Scale(size float64) Vector {
scalUnitaryTo(v, size, v) scalUnitaryTo(v, size, v)
return v return v
} }
*/
// Equal compares that two vectors are equal to each other // Equal compares that two vectors are equal to each other
func Equal(v1, v2 Vector) bool { func Equal(v1, v2 Vector) bool {