//public const int kRoutingOffset = 1 + (int)CategoryIndex.LastCategory; public bool TryGetRoute(ref RoutingTable table, CategoryGroupIndex inputIndex, out CategoryRoutingRow routingRow) { var tableIndex = startIndex + (int)inputIndex;// (inputIndex == CategoryGroupIndex.First) ? (int)CategoryGroupIndex.First : ((int)inputIndex - kRoutingOffset); if (tableIndex < startIndex || tableIndex >= endIndex) { routingRow = new CategoryRoutingRow(inputIndex); return(false); } //Debug.Assert(inputIndex == table.Value.inputs[tableIndex]); routingRow = table.routingRows[tableIndex]; return(true); }
void IntersectLoopsJob(HashedVertices brushVertices, NativeListArray <int> .NativeList loopIndices, int surfaceLoopIndex, NativeListArray <int> holeIndices, NativeList <SurfaceInfo> allInfos, NativeListArray <Edge> allEdges, NativeListArray <Edge> .NativeList intersectionLoop, CategoryGroupIndex intersectionCategory, SurfaceInfo intersectionInfo) { if (intersectionLoop.Length == 0) { return; } //Debug.Assert(allEdges.Length == allInfos.Length); //Debug.Assert(allInfos.Length == holeIndices.Length); var currentLoopEdges = allEdges[surfaceLoopIndex]; var currentInfo = allInfos[surfaceLoopIndex]; var currentHoleIndices = holeIndices[surfaceLoopIndex]; // It might look like we could just set the interiorCategory of brush_intersection here, and let all other cut loops copy from it below, // but the same brush_intersection might be used by another categorized_loop and then we'd try to reroute it again, which wouldn't work //brush_intersection.interiorCategory = newHoleCategory; if (currentLoopEdges.Length == 0) { return; } var maxLength = math.max(intersectionLoop.Length, currentLoopEdges.Length); if (maxLength < 3) { return; } int inside2 = 0, outside2 = 0; var categories2 = stackalloc EdgeCategory[currentLoopEdges.Length]; var treeSpacePlanes1 = brushTreeSpacePlanes[intersectionInfo.brushNodeIndex]; for (int e = 0; e < currentLoopEdges.Length; e++) { var category = BooleanEdgesUtility.CategorizeEdge(currentLoopEdges[e], ref treeSpacePlanes1.Value.treeSpacePlanes, intersectionLoop, brushVertices); categories2[e] = category; if (category == EdgeCategory.Inside) { inside2++; } else if (category == EdgeCategory.Outside) { outside2++; } } var aligned2 = currentLoopEdges.Length - (inside2 + outside2); int inside1 = 0, outside1 = 0; var categories1 = stackalloc EdgeCategory[intersectionLoop.Length]; var treeSpacePlanes2 = brushTreeSpacePlanes[currentInfo.brushNodeIndex]; for (int e = 0; e < intersectionLoop.Length; e++) { var category = BooleanEdgesUtility.CategorizeEdge(intersectionLoop[e], ref treeSpacePlanes2.Value.treeSpacePlanes, currentLoopEdges, brushVertices); categories1[e] = category; if (category == EdgeCategory.Inside) { inside1++; } else if (category == EdgeCategory.Outside) { outside1++; } } var aligned1 = intersectionLoop.Length - (inside1 + outside1); // Completely outside if ((inside1 + aligned1) == 0 && (aligned2 + inside2) == 0) { return; } if ((inside1 + (inside2 + aligned2)) < 3) { return; } // Completely aligned if (((outside1 + inside1) == 0 && (outside2 + inside2) == 0) || // polygon1 edges Completely inside polygon2 (inside1 == 0 && outside2 == 0)) { // New polygon overrides the existing polygon currentInfo.interiorCategory = intersectionCategory; allInfos[surfaceLoopIndex] = currentInfo; //Debug.Assert(holeIndices.IsAllocated(surfaceLoopIndex)); return; } var outEdges = stackalloc Edge[maxLength]; var outEdgesLength = 0; // polygon2 edges Completely inside polygon1 if (outside1 == 0 && inside2 == 0) { // polygon1 Completely inside polygon2 for (int n = 0; n < intersectionLoop.Length; n++) { outEdges[outEdgesLength] = intersectionLoop[n]; outEdgesLength++; } //OperationResult.Polygon1InsidePolygon2; } else { //int outEdgesLength = 0; // Can't read from outEdges.Length since it's marked as WriteOnly for (int e = 0; e < intersectionLoop.Length; e++) { var category = categories1[e]; if (category == EdgeCategory.Inside) { outEdges[outEdgesLength] = intersectionLoop[e]; outEdgesLength++; } } for (int e = 0; e < currentLoopEdges.Length; e++) { var category = categories2[e]; if (category != EdgeCategory.Outside) { outEdges[outEdgesLength] = currentLoopEdges[e]; outEdgesLength++; } } //OperationResult.Cut; } if (outEdgesLength < 3) { return; } // FIXME: when brush_intersection and categorized_loop are grazing each other, // technically we cut it but we shouldn't be creating it as a separate polygon + hole (bug7) // the output of cutting operations are both holes for the original polygon (categorized_loop) // and new polygons on the surface of the brush that need to be categorized intersectionInfo.interiorCategory = intersectionCategory; if (currentHoleIndices.Length > 0 && // TODO: fix touching not being updated properly brushesTouchedByBrushes.ContainsKey(currentInfo.brushNodeIndex)) { // Figure out why this is seemingly not necessary? var intersectedHoleIndices = stackalloc int[currentHoleIndices.Length]; var intersectedHoleIndicesLength = 0; // the output of cutting operations are both holes for the original polygon (categorized_loop) // and new polygons on the surface of the brush that need to be categorized ref var brushesTouchedByBrush = ref brushesTouchedByBrushes[currentInfo.brushNodeIndex].Value; ref var brushIntersections = ref brushesTouchedByBrushes[currentInfo.brushNodeIndex].Value.brushIntersections;