github.com/richardwilkes/toolbox@v1.121.0/xmath/geom/poly/intersection.go (about) 1 // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved. 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, version 2.0. If a copy of the MPL was not distributed with 5 // this file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 // 7 // This Source Code Form is "Incompatible With Secondary Licenses", as 8 // defined by the Mozilla Public License, version 2.0. 9 10 package poly 11 12 import ( 13 "github.com/richardwilkes/toolbox/xmath/geom" 14 "golang.org/x/exp/constraints" 15 ) 16 17 type intersection[T constraints.Float] struct { 18 edge0 *edgeNode[T] 19 edge1 *edgeNode[T] 20 point geom.Point[T] 21 next *intersection[T] 22 } 23 24 func (i *intersection[T]) process(op clipOp, pt geom.Point[T], outPoly *polygonNode[T]) *polygonNode[T] { 25 e0 := i.edge0 26 e1 := i.edge1 27 28 // Only generate output for contributing intersections 29 if (e0.bundleAbove[clipping] || e0.bundleAbove[subject]) && (e1.bundleAbove[clipping] || e1.bundleAbove[subject]) { 30 n0 := e0.outAbove 31 n1 := e1.outAbove 32 iPt := i.point 33 iPt.Y += pt.Y 34 inClip := (e0.bundleAbove[clipping] && !e0.clipSide) || 35 (e1.bundleAbove[clipping] && e1.clipSide) || 36 (!e0.bundleAbove[clipping] && !e1.bundleAbove[clipping] && e0.clipSide && e1.clipSide) 37 inSubj := (e0.bundleAbove[subject] && !e0.subjectSide) || 38 (e1.bundleAbove[subject] && e1.subjectSide) || 39 (!e0.bundleAbove[subject] && !e1.bundleAbove[subject] && e0.subjectSide && e1.subjectSide) 40 41 // Determine quadrant occupancies 42 var br, bl, tr, tl bool 43 e0InClip := inClip != e0.bundleAbove[clipping] 44 e1InClip := inClip != e1.bundleAbove[clipping] 45 e0InSubj := inSubj != e0.bundleAbove[subject] 46 e1InSubj := inSubj != e1.bundleAbove[subject] 47 e10InClip := e1InClip != e0.bundleAbove[clipping] 48 e10InSubj := e1InSubj != e0.bundleAbove[subject] 49 switch op { 50 case subtractOp, intersectOp: 51 tr = inClip && inSubj 52 tl = e1InClip && e1InSubj 53 br = e0InClip && e0InSubj 54 bl = e10InClip && e10InSubj 55 case xorOp: 56 tr = inClip != inSubj 57 tl = e1InClip != e1InSubj 58 br = e0InClip != e0InSubj 59 bl = e10InClip != e10InSubj 60 case unionOp: 61 tr = inClip || inSubj 62 tl = e1InClip || e1InSubj 63 br = e0InClip || e0InSubj 64 bl = e10InClip || e10InSubj 65 } 66 switch calcVertexType(tr, tl, br, bl) { 67 case externalMinimum: 68 outPoly = e0.addLocalMin(outPoly, iPt) 69 e1.outAbove = e0.outAbove 70 case externalRightIntermediate: 71 if n0 != nil { 72 n0.addRight(iPt) 73 e1.outAbove = n0 74 e0.outAbove = nil 75 } 76 case externalLeftIntermediate: 77 if n1 != nil { 78 n1.addLeft(iPt) 79 e0.outAbove = n1 80 e1.outAbove = nil 81 } 82 case externalMaximum: 83 if n0 != nil && n1 != nil { 84 n0.addLeft(iPt) 85 n0.mergeRight(n1, outPoly) 86 e0.outAbove = nil 87 e1.outAbove = nil 88 } 89 case internalMinimum: 90 outPoly = e0.addLocalMin(outPoly, iPt) 91 e1.outAbove = e0.outAbove 92 case internalLeftIntermediate: 93 if n0 != nil { 94 n0.addLeft(iPt) 95 e1.outAbove = n0 96 e0.outAbove = nil 97 } 98 case internalRightIntermediate: 99 if n1 != nil { 100 n1.addRight(iPt) 101 e0.outAbove = n1 102 e1.outAbove = nil 103 } 104 case internalMaximum: 105 if n0 != nil && n1 != nil { 106 n0.addRight(iPt) 107 n0.mergeLeft(n1, outPoly) 108 e0.outAbove = nil 109 e1.outAbove = nil 110 } 111 case internalMaximumAndMinimum: 112 if n0 != nil && n1 != nil { 113 n0.addRight(iPt) 114 n0.mergeLeft(n1, outPoly) 115 outPoly = e0.addLocalMin(outPoly, iPt) 116 e1.outAbove = e0.outAbove 117 } 118 case externalMaximumAndMinimum: 119 if n0 != nil && n1 != nil { 120 n0.addLeft(iPt) 121 n0.mergeRight(n1, outPoly) 122 outPoly = e0.addLocalMin(outPoly, iPt) 123 e1.outAbove = e0.outAbove 124 } 125 default: 126 } 127 } 128 129 // Swap bundle sides in response to edge crossing 130 if e0.bundleAbove[clipping] { 131 e1.clipSide = !e1.clipSide 132 } 133 if e1.bundleAbove[clipping] { 134 e0.clipSide = !e0.clipSide 135 } 136 if e0.bundleAbove[subject] { 137 e1.subjectSide = !e1.subjectSide 138 } 139 if e1.bundleAbove[subject] { 140 e0.subjectSide = !e0.subjectSide 141 } 142 143 return outPoly 144 }