 9bdcbe0447
			
		
	
	9bdcbe0447
	
	
	
		
			
			Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			414 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			414 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2017 Google Inc. All rights reserved.
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //     http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| package s2
 | |
| 
 | |
| import (
 | |
| 	"sort"
 | |
| 
 | |
| 	"github.com/blevesearch/geo/r2"
 | |
| )
 | |
| 
 | |
| // CrossingEdgeQuery is used to find the Edge IDs of Shapes that are crossed by
 | |
| // a given edge(s).
 | |
| //
 | |
| // Note that if you need to query many edges, it is more efficient to declare
 | |
| // a single CrossingEdgeQuery instance and reuse it.
 | |
| //
 | |
| // If you want to find *all* the pairs of crossing edges, it is more efficient to
 | |
| // use the not yet implemented VisitCrossings in shapeutil.
 | |
| type CrossingEdgeQuery struct {
 | |
| 	index *ShapeIndex
 | |
| 
 | |
| 	// temporary values used while processing a query.
 | |
| 	a, b r2.Point
 | |
| 	iter *ShapeIndexIterator
 | |
| 
 | |
| 	// candidate cells generated when finding crossings.
 | |
| 	cells []*ShapeIndexCell
 | |
| }
 | |
| 
 | |
| // NewCrossingEdgeQuery creates a CrossingEdgeQuery for the given index.
 | |
| func NewCrossingEdgeQuery(index *ShapeIndex) *CrossingEdgeQuery {
 | |
| 	c := &CrossingEdgeQuery{
 | |
| 		index: index,
 | |
| 		iter:  index.Iterator(),
 | |
| 	}
 | |
| 	return c
 | |
| }
 | |
| 
 | |
| // Crossings returns the set of edge of the shape S that intersect the given edge AB.
 | |
| // If the CrossingType is Interior, then only intersections at a point interior to both
 | |
| // edges are reported, while if it is CrossingTypeAll then edges that share a vertex
 | |
| // are also reported.
 | |
| func (c *CrossingEdgeQuery) Crossings(a, b Point, shape Shape, crossType CrossingType) []int {
 | |
| 	edges := c.candidates(a, b, shape)
 | |
| 	if len(edges) == 0 {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	crosser := NewEdgeCrosser(a, b)
 | |
| 	out := 0
 | |
| 	n := len(edges)
 | |
| 
 | |
| 	for in := 0; in < n; in++ {
 | |
| 		b := shape.Edge(edges[in])
 | |
| 		sign := crosser.CrossingSign(b.V0, b.V1)
 | |
| 		if crossType == CrossingTypeAll && (sign == MaybeCross || sign == Cross) || crossType != CrossingTypeAll && sign == Cross {
 | |
| 			edges[out] = edges[in]
 | |
| 			out++
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if out < n {
 | |
| 		edges = edges[0:out]
 | |
| 	}
 | |
| 	return edges
 | |
| }
 | |
| 
 | |
| // EdgeMap stores a sorted set of edge ids for each shape.
 | |
| type EdgeMap map[Shape][]int
 | |
| 
 | |
| // CrossingsEdgeMap returns the set of all edges in the index that intersect the given
 | |
| // edge AB. If crossType is CrossingTypeInterior, then only intersections at a
 | |
| // point interior to both edges are reported, while if it is CrossingTypeAll
 | |
| // then edges that share a vertex are also reported.
 | |
| //
 | |
| // The edges are returned as a mapping from shape to the edges of that shape
 | |
| // that intersect AB. Every returned shape has at least one crossing edge.
 | |
| func (c *CrossingEdgeQuery) CrossingsEdgeMap(a, b Point, crossType CrossingType) EdgeMap {
 | |
| 	edgeMap := c.candidatesEdgeMap(a, b)
 | |
| 	if len(edgeMap) == 0 {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	crosser := NewEdgeCrosser(a, b)
 | |
| 	for shape, edges := range edgeMap {
 | |
| 		out := 0
 | |
| 		n := len(edges)
 | |
| 		for in := 0; in < n; in++ {
 | |
| 			edge := shape.Edge(edges[in])
 | |
| 			sign := crosser.CrossingSign(edge.V0, edge.V1)
 | |
| 			if (crossType == CrossingTypeAll && (sign == MaybeCross || sign == Cross)) || (crossType != CrossingTypeAll && sign == Cross) {
 | |
| 				edgeMap[shape][out] = edges[in]
 | |
| 				out++
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if out == 0 {
 | |
| 			delete(edgeMap, shape)
 | |
| 		} else {
 | |
| 			if out < n {
 | |
| 				edgeMap[shape] = edgeMap[shape][0:out]
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return edgeMap
 | |
| }
 | |
| 
 | |
| // candidates returns a superset of the edges of the given shape that intersect
 | |
| // the edge AB.
 | |
| func (c *CrossingEdgeQuery) candidates(a, b Point, shape Shape) []int {
 | |
| 	var edges []int
 | |
| 
 | |
| 	// For small loops it is faster to use brute force. The threshold below was
 | |
| 	// determined using benchmarks.
 | |
| 	const maxBruteForceEdges = 27
 | |
| 	maxEdges := shape.NumEdges()
 | |
| 	if maxEdges <= maxBruteForceEdges {
 | |
| 		edges = make([]int, maxEdges)
 | |
| 		for i := 0; i < maxEdges; i++ {
 | |
| 			edges[i] = i
 | |
| 		}
 | |
| 		return edges
 | |
| 	}
 | |
| 
 | |
| 	// Compute the set of index cells intersected by the query edge.
 | |
| 	c.getCellsForEdge(a, b)
 | |
| 	if len(c.cells) == 0 {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	// Gather all the edges that intersect those cells and sort them.
 | |
| 	// TODO(roberts): Shapes don't track their ID, so we need to range over
 | |
| 	// the index to find the ID manually.
 | |
| 	var shapeID int32
 | |
| 	for k, v := range c.index.shapes {
 | |
| 		if v == shape {
 | |
| 			shapeID = k
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	for _, cell := range c.cells {
 | |
| 		if cell == nil {
 | |
| 			continue
 | |
| 		}
 | |
| 		clipped := cell.findByShapeID(shapeID)
 | |
| 		if clipped == nil {
 | |
| 			continue
 | |
| 		}
 | |
| 		edges = append(edges, clipped.edges...)
 | |
| 	}
 | |
| 
 | |
| 	if len(c.cells) > 1 {
 | |
| 		edges = uniqueInts(edges)
 | |
| 	}
 | |
| 
 | |
| 	return edges
 | |
| }
 | |
| 
 | |
| // uniqueInts returns the sorted uniqued values from the given input.
 | |
| func uniqueInts(in []int) []int {
 | |
| 	var edges []int
 | |
| 	m := make(map[int]bool)
 | |
| 	for _, i := range in {
 | |
| 		if m[i] {
 | |
| 			continue
 | |
| 		}
 | |
| 		m[i] = true
 | |
| 		edges = append(edges, i)
 | |
| 	}
 | |
| 	sort.Ints(edges)
 | |
| 	return edges
 | |
| }
 | |
| 
 | |
| // candidatesEdgeMap returns a map from shapes to the superse of edges for that
 | |
| // shape that intersect the edge AB.
 | |
| //
 | |
| // CAVEAT: This method may return shapes that have an empty set of candidate edges.
 | |
| // However the return value is non-empty only if at least one shape has a candidate edge.
 | |
| func (c *CrossingEdgeQuery) candidatesEdgeMap(a, b Point) EdgeMap {
 | |
| 	edgeMap := make(EdgeMap)
 | |
| 
 | |
| 	// If there are only a few edges then it's faster to use brute force. We
 | |
| 	// only bother with this optimization when there is a single shape.
 | |
| 	if len(c.index.shapes) == 1 {
 | |
| 		// Typically this method is called many times, so it is worth checking
 | |
| 		// whether the edge map is empty or already consists of a single entry for
 | |
| 		// this shape, and skip clearing edge map in that case.
 | |
| 		shape := c.index.Shape(0)
 | |
| 
 | |
| 		// Note that we leave the edge map non-empty even if there are no candidates
 | |
| 		// (i.e., there is a single entry with an empty set of edges).
 | |
| 		edgeMap[shape] = c.candidates(a, b, shape)
 | |
| 		return edgeMap
 | |
| 	}
 | |
| 
 | |
| 	// Compute the set of index cells intersected by the query edge.
 | |
| 	c.getCellsForEdge(a, b)
 | |
| 	if len(c.cells) == 0 {
 | |
| 		return edgeMap
 | |
| 	}
 | |
| 
 | |
| 	// Gather all the edges that intersect those cells and sort them.
 | |
| 	for _, cell := range c.cells {
 | |
| 		for _, clipped := range cell.shapes {
 | |
| 			s := c.index.Shape(clipped.shapeID)
 | |
| 			for j := 0; j < clipped.numEdges(); j++ {
 | |
| 				edgeMap[s] = append(edgeMap[s], clipped.edges[j])
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if len(c.cells) > 1 {
 | |
| 		for s, edges := range edgeMap {
 | |
| 			edgeMap[s] = uniqueInts(edges)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return edgeMap
 | |
| }
 | |
| 
 | |
| // getCells returns the set of ShapeIndexCells that might contain edges intersecting
 | |
| // the edge AB in the given cell root. This method is used primarily by loop and shapeutil.
 | |
| func (c *CrossingEdgeQuery) getCells(a, b Point, root *PaddedCell) []*ShapeIndexCell {
 | |
| 	aUV, bUV, ok := ClipToFace(a, b, root.id.Face())
 | |
| 	if ok {
 | |
| 		c.a = aUV
 | |
| 		c.b = bUV
 | |
| 		edgeBound := r2.RectFromPoints(c.a, c.b)
 | |
| 		if root.Bound().Intersects(edgeBound) {
 | |
| 			c.computeCellsIntersected(root, edgeBound)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if len(c.cells) == 0 {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	return c.cells
 | |
| }
 | |
| 
 | |
| // getCellsForEdge populates the cells field to the set of index cells intersected by an edge AB.
 | |
| func (c *CrossingEdgeQuery) getCellsForEdge(a, b Point) {
 | |
| 	c.cells = nil
 | |
| 
 | |
| 	segments := FaceSegments(a, b)
 | |
| 	for _, segment := range segments {
 | |
| 		c.a = segment.a
 | |
| 		c.b = segment.b
 | |
| 
 | |
| 		// Optimization: rather than always starting the recursive subdivision at
 | |
| 		// the top level face cell, instead we start at the smallest S2CellId that
 | |
| 		// contains the edge (the edge root cell). This typically lets us skip
 | |
| 		// quite a few levels of recursion since most edges are short.
 | |
| 		edgeBound := r2.RectFromPoints(c.a, c.b)
 | |
| 		pcell := PaddedCellFromCellID(CellIDFromFace(segment.face), 0)
 | |
| 		edgeRoot := pcell.ShrinkToFit(edgeBound)
 | |
| 
 | |
| 		// Now we need to determine how the edge root cell is related to the cells
 | |
| 		// in the spatial index (cellMap). There are three cases:
 | |
| 		//
 | |
| 		//  1. edgeRoot is an index cell or is contained within an index cell.
 | |
| 		//     In this case we only need to look at the contents of that cell.
 | |
| 		//  2. edgeRoot is subdivided into one or more index cells. In this case
 | |
| 		//     we recursively subdivide to find the cells intersected by AB.
 | |
| 		//  3. edgeRoot does not intersect any index cells. In this case there
 | |
| 		//     is nothing to do.
 | |
| 		relation := c.iter.LocateCellID(edgeRoot)
 | |
| 		switch relation {
 | |
| 		case Indexed:
 | |
| 			// edgeRoot is an index cell or is contained by an
 | |
| 			// index cell (case 1).
 | |
| 			c.cells = append(c.cells, c.iter.IndexCell())
 | |
| 		case Subdivided:
 | |
| 			// edgeRoot is subdivided into one or more index cells
 | |
| 			// (case 2). We find the cells intersected by AB using
 | |
| 			// recursive subdivision.
 | |
| 			if !edgeRoot.isFace() {
 | |
| 				pcell = PaddedCellFromCellID(edgeRoot, 0)
 | |
| 			}
 | |
| 			c.computeCellsIntersected(pcell, edgeBound)
 | |
| 		case Disjoint:
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // computeCellsIntersected computes the index cells intersected by the current
 | |
| // edge that are descendants of pcell and adds them to this queries set of cells.
 | |
| func (c *CrossingEdgeQuery) computeCellsIntersected(pcell *PaddedCell, edgeBound r2.Rect) {
 | |
| 
 | |
| 	c.iter.seek(pcell.id.RangeMin())
 | |
| 	if c.iter.Done() || c.iter.CellID() > pcell.id.RangeMax() {
 | |
| 		// The index does not contain pcell or any of its descendants.
 | |
| 		return
 | |
| 	}
 | |
| 	if c.iter.CellID() == pcell.id {
 | |
| 		// The index contains this cell exactly.
 | |
| 		c.cells = append(c.cells, c.iter.IndexCell())
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Otherwise, split the edge among the four children of pcell.
 | |
| 	center := pcell.Middle().Lo()
 | |
| 
 | |
| 	if edgeBound.X.Hi < center.X {
 | |
| 		// Edge is entirely contained in the two left children.
 | |
| 		c.clipVAxis(edgeBound, center.Y, 0, pcell)
 | |
| 		return
 | |
| 	} else if edgeBound.X.Lo >= center.X {
 | |
| 		// Edge is entirely contained in the two right children.
 | |
| 		c.clipVAxis(edgeBound, center.Y, 1, pcell)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	childBounds := c.splitUBound(edgeBound, center.X)
 | |
| 	if edgeBound.Y.Hi < center.Y {
 | |
| 		// Edge is entirely contained in the two lower children.
 | |
| 		c.computeCellsIntersected(PaddedCellFromParentIJ(pcell, 0, 0), childBounds[0])
 | |
| 		c.computeCellsIntersected(PaddedCellFromParentIJ(pcell, 1, 0), childBounds[1])
 | |
| 	} else if edgeBound.Y.Lo >= center.Y {
 | |
| 		// Edge is entirely contained in the two upper children.
 | |
| 		c.computeCellsIntersected(PaddedCellFromParentIJ(pcell, 0, 1), childBounds[0])
 | |
| 		c.computeCellsIntersected(PaddedCellFromParentIJ(pcell, 1, 1), childBounds[1])
 | |
| 	} else {
 | |
| 		// The edge bound spans all four children. The edge itself intersects
 | |
| 		// at most three children (since no padding is being used).
 | |
| 		c.clipVAxis(childBounds[0], center.Y, 0, pcell)
 | |
| 		c.clipVAxis(childBounds[1], center.Y, 1, pcell)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // clipVAxis computes the intersected cells recursively for a given padded cell.
 | |
| // Given either the left (i=0) or right (i=1) side of a padded cell pcell,
 | |
| // determine whether the current edge intersects the lower child, upper child,
 | |
| // or both children, and call c.computeCellsIntersected recursively on those children.
 | |
| // The center is the v-coordinate at the center of pcell.
 | |
| func (c *CrossingEdgeQuery) clipVAxis(edgeBound r2.Rect, center float64, i int, pcell *PaddedCell) {
 | |
| 	if edgeBound.Y.Hi < center {
 | |
| 		// Edge is entirely contained in the lower child.
 | |
| 		c.computeCellsIntersected(PaddedCellFromParentIJ(pcell, i, 0), edgeBound)
 | |
| 	} else if edgeBound.Y.Lo >= center {
 | |
| 		// Edge is entirely contained in the upper child.
 | |
| 		c.computeCellsIntersected(PaddedCellFromParentIJ(pcell, i, 1), edgeBound)
 | |
| 	} else {
 | |
| 		// The edge intersects both children.
 | |
| 		childBounds := c.splitVBound(edgeBound, center)
 | |
| 		c.computeCellsIntersected(PaddedCellFromParentIJ(pcell, i, 0), childBounds[0])
 | |
| 		c.computeCellsIntersected(PaddedCellFromParentIJ(pcell, i, 1), childBounds[1])
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // splitUBound returns the bound for two children as a result of splitting the
 | |
| // current edge at the given value U.
 | |
| func (c *CrossingEdgeQuery) splitUBound(edgeBound r2.Rect, u float64) [2]r2.Rect {
 | |
| 	v := edgeBound.Y.ClampPoint(interpolateFloat64(u, c.a.X, c.b.X, c.a.Y, c.b.Y))
 | |
| 	// diag indicates which diagonal of the bounding box is spanned by AB:
 | |
| 	// it is 0 if AB has positive slope, and 1 if AB has negative slope.
 | |
| 	var diag int
 | |
| 	if (c.a.X > c.b.X) != (c.a.Y > c.b.Y) {
 | |
| 		diag = 1
 | |
| 	}
 | |
| 	return splitBound(edgeBound, 0, diag, u, v)
 | |
| }
 | |
| 
 | |
| // splitVBound returns the bound for two children as a result of splitting the
 | |
| // current edge into two child edges at the given value V.
 | |
| func (c *CrossingEdgeQuery) splitVBound(edgeBound r2.Rect, v float64) [2]r2.Rect {
 | |
| 	u := edgeBound.X.ClampPoint(interpolateFloat64(v, c.a.Y, c.b.Y, c.a.X, c.b.X))
 | |
| 	var diag int
 | |
| 	if (c.a.X > c.b.X) != (c.a.Y > c.b.Y) {
 | |
| 		diag = 1
 | |
| 	}
 | |
| 	return splitBound(edgeBound, diag, 0, u, v)
 | |
| }
 | |
| 
 | |
| // splitBound returns the bounds for the two childrenn as a result of splitting
 | |
| // the current edge into two child edges at the given point (u,v). uEnd and vEnd
 | |
| // indicate which bound endpoints of the first child will be updated.
 | |
| func splitBound(edgeBound r2.Rect, uEnd, vEnd int, u, v float64) [2]r2.Rect {
 | |
| 	var childBounds = [2]r2.Rect{
 | |
| 		edgeBound,
 | |
| 		edgeBound,
 | |
| 	}
 | |
| 
 | |
| 	if uEnd == 1 {
 | |
| 		childBounds[0].X.Lo = u
 | |
| 		childBounds[1].X.Hi = u
 | |
| 	} else {
 | |
| 		childBounds[0].X.Hi = u
 | |
| 		childBounds[1].X.Lo = u
 | |
| 	}
 | |
| 
 | |
| 	if vEnd == 1 {
 | |
| 		childBounds[0].Y.Lo = v
 | |
| 		childBounds[1].Y.Hi = v
 | |
| 	} else {
 | |
| 		childBounds[0].Y.Hi = v
 | |
| 		childBounds[1].Y.Lo = v
 | |
| 	}
 | |
| 
 | |
| 	return childBounds
 | |
| }
 |