public static OctreeChild Create(BoundingBox bounds, List <OctreeFace> faces, int depth = -1) { depth++; OctreeChild node = new OctreeChild(); Vector3 centre = (bounds.Min + bounds.Max) * 0.5f; BoundingBox childBounds = new BoundingBox(); SplitFlags splitFlags = 0; if (depth > Octree.MaxDepth || (depth > 0 && faces.Count < Octree.MaxFacesPerLeaf)) { splitFlags = 0; if (faces.Count > Octree.MaxFacesPerLeaf / 8) { if (bounds.Max.X - bounds.Min.X > 100.0f) { splitFlags |= SplitFlags.SplitInX; } if (bounds.Max.Z - bounds.Min.Z > 100.0f) { splitFlags |= SplitFlags.SplitInZ; } } if (splitFlags == 0) { node = OctreeLeaf.Create(depth, faces); depth--; return(node); } } else { DetermineSplittage(depth, faces, centre, ref splitFlags); } if (depth > 0 && splitFlags == 0) { node = OctreeLeaf.Create(depth, faces); depth--; return(node); } //numNodes++; node = new OctreeNode { ChildType = 0, Flags = splitFlags }; for (int i = 0; i < (node as OctreeNode).Children.Length; i++) { if (node.Flags.HasFlag(SplitFlags.SplitInX)) { if ((i & 1) == 1) { childBounds.Min.X = centre.X; childBounds.Max.X = bounds.Max.X; } else { childBounds.Min.X = bounds.Min.X; childBounds.Max.X = centre.X; } } else { if ((i & 1) == 1) { continue; } else { childBounds.Min.X = bounds.Min.X; childBounds.Max.X = bounds.Max.X; } } if (node.Flags.HasFlag(SplitFlags.SplitInY)) { if ((i & 2) == 2) { childBounds.Min.Y = centre.Y; childBounds.Max.Y = bounds.Max.Y; } else { childBounds.Min.Y = bounds.Min.Y; childBounds.Max.Y = centre.Y; } } else { if ((i & 2) == 2) { continue; } else { childBounds.Min.Y = bounds.Min.Y; childBounds.Max.Y = bounds.Max.Y; } } if (node.Flags.HasFlag(SplitFlags.SplitInZ)) { if ((i & 4) == 4) { childBounds.Min.Z = centre.Z; childBounds.Max.Z = bounds.Max.Z; } else { childBounds.Min.Z = bounds.Min.Z; childBounds.Max.Z = centre.Z; } } else { if ((i & 4) == 4) { continue; } else { childBounds.Min.Z = bounds.Min.Z; childBounds.Max.Z = bounds.Max.Z; } } //Logger.LogToFile(Logger.LogLevel.All, $"{depth}\t{i}\t{childBounds.Min}\t{childBounds.Max}"); List <OctreeFace> childFaces = Octree.FindFacesFromList(faces, childBounds); (node as OctreeNode).Children[i] = Create(childBounds, childFaces, depth); } depth--; return(node); }
public static PhpArray Split(object pattern, object data, int limit, SplitFlags flags) { if (limit == 0) // 0 does not make sense, php's behavior is as it is -1 limit = -1; if (limit < -1) // for all other negative values it seems that is as limit == 1 limit = 1; PerlRegExpConverter converter = ConvertPattern(pattern, null); if (converter == null) return null; string str = ConvertData(data, converter); Match m = converter.Regex.Match(str); bool offset_capture = (flags & SplitFlags.OffsetCapture) != 0; PhpArray result = new PhpArray(); int last_index = 0; while (m.Success && (limit == -1 || --limit > 0) && last_index < str.Length) { // add part before match int length = m.Index - last_index; if (length > 0 || (flags & SplitFlags.NoEmpty) == 0) result.Add(NewArrayItem(str.Substring(last_index, length), last_index, offset_capture)); if (m.Value.Length > 0) { if ((flags & SplitFlags.DelimCapture) != 0) // add all captures but not whole pattern match (start at 1) { List<object> lastUnsucessfulGroups = null; // value of groups that was not successful since last succesful one for (int i = 1; i < m.Groups.Count; i++) { Group g = m.Groups[i]; if (g.Length > 0 || (flags & SplitFlags.NoEmpty) == 0) { // the value to be added into the result: object value = NewArrayItem(g.Value, g.Index, offset_capture); if (g.Success) { // group {i} was matched: // if there was some unsuccesfull matches before, add them now: if (lastUnsucessfulGroups != null && lastUnsucessfulGroups.Count > 0) { foreach (var x in lastUnsucessfulGroups) result.Add(x); lastUnsucessfulGroups.Clear(); } // add the matched group: result.Add(value); } else { // The match was unsuccesful, remember all the unsuccesful matches // and add them only if some succesful match will follow. // In PHP, unsuccessfully matched groups are trimmed by the end // (regexp processing stops when other groups cannot be matched): if (lastUnsucessfulGroups == null) lastUnsucessfulGroups = new List<object>(); lastUnsucessfulGroups.Add(value); } } } } last_index = m.Index + m.Length; } else // regular expression match an empty string => add one character { // always not empty result.Add(NewArrayItem(str.Substring(last_index, 1), last_index, offset_capture)); last_index++; } m = m.NextMatch(); } // add remaining string (might be empty) if (last_index < str.Length || (flags & SplitFlags.NoEmpty) == 0) result.Add(NewArrayItem(str.Substring(last_index), last_index, offset_capture)); return result; }
public static void DetermineSplittage(int depth, List <OctreeFace> faces, Vector3 centre, ref SplitFlags splitFlags) { int nFacesXMin = 0, nFacesXMax = 0; int nFacesYMin = 0, nFacesYMax = 0; int nFacesZMin = 0, nFacesZMax = 0; for (int i = 0; i < faces.Count; i++) { OctreeFace face = faces[i]; if (face.HitNumber == depth || face.HitNumber < 0) { if (face.Vertices[0].X < centre.X && face.Vertices[1].X < centre.X && face.Vertices[2].X < centre.X) { nFacesXMin++; } if (face.Vertices[0].X > centre.X && face.Vertices[1].X > centre.X && face.Vertices[2].X > centre.X) { nFacesXMax++; } if (face.Vertices[0].Y < centre.Y && face.Vertices[1].Y < centre.Y && face.Vertices[2].Y < centre.Y) { nFacesYMin++; } if (face.Vertices[0].Y > centre.Y && face.Vertices[1].Y > centre.Y && face.Vertices[2].Y > centre.Y) { nFacesYMax++; } if (face.Vertices[0].Z < centre.Z && face.Vertices[1].Z < centre.Z && face.Vertices[2].Z < centre.Z) { nFacesZMin++; } if (face.Vertices[0].Z > centre.Z && face.Vertices[1].Z > centre.Z && face.Vertices[2].Z > centre.Z) { nFacesZMax++; } } } splitFlags = 0; if (nFacesXMin + nFacesXMax > Octree.NodeSplitParameter * faces.Count) { splitFlags |= SplitFlags.SplitInX; } if (nFacesYMin + nFacesYMax > Octree.NodeSplitParameter * faces.Count) { splitFlags |= SplitFlags.SplitInY; } if (nFacesZMin + nFacesZMax > Octree.NodeSplitParameter * faces.Count) { splitFlags |= SplitFlags.SplitInZ; } }