github.com/pavlo67/common@v0.5.3/common/mathlib/plane/lines.go (about) 1 package plane 2 3 import ( 4 "math" 5 6 "github.com/pavlo67/common/common/mathlib" 7 ) 8 9 type Intersection struct { 10 Angle float64 11 X0, X1 float64 12 } 13 14 func Cross(p1, p2 Point2) float64 { 15 return p1.X*p2.Y - p1.Y*p2.X 16 } 17 18 func (s Segment) TurnAroundAxis(p2 Point2) Point2 { 19 axisDX, axisDY := s[1].X-s[0].X, s[1].Y-s[0].Y 20 var axisDerivative float64 21 22 if axisDX == 0 { 23 if axisDY == 0 { 24 // TODO!!! be careful, it's a very non-standard case 25 return Point2{s[0].X*2 - p2.X, s[0].Y*2 - p2.Y} 26 } 27 return Point2{s[0].X*2 - p2.X, p2.Y} 28 } else if axisDerivative = axisDY / axisDX; math.IsInf(axisDerivative, 0) { 29 return Point2{s[0].X*2 - p2.X, p2.Y} 30 } else if axisDY == 0 || math.IsInf(1/axisDerivative, 0) { 31 return Point2{p2.X, s[0].Y*2 - p2.Y} 32 } 33 34 pIntersection := s.LinesIntersection(Segment{p2, Point2{p2.X + 1, p2.Y - 1/axisDerivative}}) 35 return Point2{pIntersection.X*2 - p2.X, pIntersection.Y*2 - p2.Y} 36 37 } 38 39 func (s Segment) TurnAroundAxisMultiple(p2s ...Point2) []Point2 { 40 axisDX, axisDY := s[1].X-s[0].X, s[1].Y-s[0].Y 41 var axisDerivative float64 42 43 p2sTurned := make([]Point2, len(p2s)) 44 45 if axisDX == 0 { 46 if axisDY == 0 { 47 // TODO!!! be careful, it's a very non-standard case 48 for i, p2 := range p2s { 49 p2sTurned[i] = Point2{s[0].X*2 - p2.X, s[0].Y*2 - p2.Y} 50 } 51 } else { 52 for i, p2 := range p2s { 53 p2sTurned[i] = Point2{s[0].X*2 - p2.X, p2.Y} 54 } 55 } 56 } else if axisDerivative = axisDY / axisDX; math.IsInf(axisDerivative, 0) { 57 for i, p2 := range p2s { 58 p2sTurned[i] = Point2{s[0].X*2 - p2.X, p2.Y} 59 } 60 } else if axisDY == 0 || math.IsInf(1/axisDerivative, 0) { 61 for i, p2 := range p2s { 62 p2sTurned[i] = Point2{p2.X, s[0].Y*2 - p2.Y} 63 } 64 } else { 65 for i, p2 := range p2s { 66 pIntersection := s.LinesIntersection(Segment{p2, Point2{p2.X + 1, p2.Y - 1/axisDerivative}}) 67 p2sTurned[i] = Point2{pIntersection.X*2 - p2.X, pIntersection.Y*2 - p2.Y} 68 } 69 } 70 71 return p2sTurned 72 } 73 74 func (s Segment) LinesIntersection(s1 Segment) *Point2 { 75 // https://stackoverflow.com/questions/7446126/opencv-2d-line-intersection-helper-function 76 // https://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect 77 78 r := Point2{s[1].X - s[0].X, s[1].Y - s[0].Y} 79 l := Point2{s1[1].X - s1[0].X, s1[1].Y - s1[0].Y} 80 81 cr := Cross(r, l) 82 if cr > -mathlib.Eps && cr < mathlib.Eps { 83 // lines are about parallel (they may be collinear!) 84 return nil 85 } 86 87 q := Point2{s1[0].X - s[0].X, s1[0].Y - s[0].Y} 88 t := Cross(q, l) / cr 89 90 return &Point2{s[0].X + t*r.X, s[0].Y + t*r.Y} 91 92 } 93 94 func (s Segment) DivideByLine(p0, p1 Point2) *Point2 { 95 pIntersect := s.LinesIntersection(Segment{p0, p1}) 96 if pIntersect == nil { 97 return nil 98 } 99 100 if p1.X > p0.X { 101 if pIntersect.X > p0.X && pIntersect.X < p1.X { 102 return pIntersect 103 } 104 } else if p1.X < p0.X { 105 if pIntersect.X > p1.X && pIntersect.X < p0.X { 106 return pIntersect 107 } 108 } else if p1.Y > p0.Y { 109 if pIntersect.Y > p0.Y && pIntersect.Y < p1.Y { 110 return pIntersect 111 } 112 } else { 113 if pIntersect.Y > p1.Y && pIntersect.Y < p0.Y { 114 return pIntersect 115 } 116 } 117 118 // log.Print(p0, p1, pIntersect) 119 120 return nil 121 }