public void RemoveBack(long consumed) { while (consumed > 0) { Segment?endSegment = _endSegment; if (endSegment == null) { ThrowHelper.ThrowArgumentOutOfRange(nameof(consumed)); } int length = endSegment.End - endSegment.Start; if (length > consumed) { endSegment.RemoveBack((int)consumed); consumed = 0; } else { _endSegment = endSegment.Previous; _endSegment?.SetNext(null); ReturnSegment(endSegment); consumed -= length; } } if (_endSegment == null) { _startSegment = null; } }
public void Remove(long consumed) { while (consumed > 0) { Segment?startSegment = _startSegment; if (startSegment == null) { ThrowHelper.ThrowArgumentOutOfRange(nameof(consumed)); } int length = startSegment.End - startSegment.Start; if (length > consumed) { startSegment.Remove((int)consumed); consumed = 0; } else { _startSegment = startSegment.Next; ReturnSegment(startSegment); consumed -= length; } } if (_startSegment == null) { _endSegment = null; } }
/// <summary>Initializes the queue.</summary> public SingleProducerSingleConsumerQueue() { // Validate constants in ctor rather than in an explicit cctor that would cause perf degradation Debug.Assert(InitialSegmentSize > 0, "Initial segment size must be > 0."); Debug.Assert((InitialSegmentSize & (InitialSegmentSize - 1)) == 0, "Initial segment size must be a power of 2"); Debug.Assert(InitialSegmentSize <= MaxSegmentSize, "Initial segment size should be <= maximum."); Debug.Assert(MaxSegmentSize < int.MaxValue / 2, "Max segment size * 2 must be < Int32.MaxValue, or else overflow could occur."); // Initialize the queue _head = _tail = new Segment(InitialSegmentSize); }
/// <summary>Gets an enumerable for the collection.</summary> /// <remarks>WARNING: This should only be used for debugging purposes. It is not safe to be used concurrently.</remarks> public IEnumerator <T> GetEnumerator() { for (Segment?segment = _head; segment != null; segment = segment._next) { for (int pt = segment._state._first; pt != segment._state._last; pt = (pt + 1) & (segment._array.Length - 1)) { yield return(segment._array[pt]); } } }
// Plays the given segments on the players. private async Task PlaySegmentsAsync(Segment?segmentForPlayerA, Segment?segmentForPlayerB) { // Draw a highlight around the players that are playing a segment. UpdatePlayerHighlights(segmentForPlayerA.HasValue, segmentForPlayerB.HasValue); // Start playing the segments. var tasks = new[] { segmentForPlayerA?.PlayAsync(PlayerA), segmentForPlayerB?.PlayAsync(PlayerB) }; // Wait for the segments to finish. await Task.WhenAll(tasks.Where(t => t is not null).ToArray()); // Remove the highlight drawn around the playing players. UpdatePlayerHighlights(false, false); }
// https://stackoverflow.com/a/565282/3333753 static public bool Intersects(this Segment segmentA, Segment segmentB, out Segment?intersection) { Vector2 vectorA = segmentA.Vector; Vector2 vectorB = segmentB.Vector; Vector2 p0Diff = segmentB.P0 - segmentA.P0; float b = p0Diff.Cross(vectorB); float abCross = vectorA.Cross(vectorB); // Check if segments are parallel if (abCross.EqualsZero()) { // Check if segments are colinear if (b.EqualsZero()) { float aaDot = Vector2.Dot(vectorA, vectorA); float baDot = Vector2.Dot(vectorB, vectorA); float t0 = Vector2.Dot(p0Diff, vectorA) / aaDot; float t1 = t0 + baDot / aaDot; Range <float> t01 = baDot >= 0 ? new Range <float>(t0, t1) : new Range <float>(t1, t0); // Check if segments are overlapping if (RangeUtils.Intersects(t01, new Range <float>(0, 1))) { intersection = new Segment(segmentA.P0 + t01.Min * vectorA, segmentA.P0 + t01.Max * vectorA); return(true); } } } else { float a = p0Diff.Cross(vectorA); float t = a / abCross; float u = b / abCross; // Check if intersect at one point if (t >= 0 && t <= 1 && u >= 0 && u <= 1) { Vector2 intersectionPoint = segmentA.P0 + t * vectorA; intersection = new Segment(intersectionPoint, intersectionPoint); return(true); } } intersection = null; return(false); }
private void AddSegment(int sizeHint) { Segment?previousEnd = _endSegment; _endSegment = SequencePool.RentSegment(); _endSegment.SetBuffer(SequencePool.RentByteBuffer(sizeHint)); if (_startSegment == null) { _startSegment = _endSegment; } else { previousEnd !.SetNext(_endSegment); } }
public void Discard(int length) { Debug.Assert(length >= 0); Debug.Assert(length <= _activeLength); _activeLength -= length; bool monitorEntered = false; try { do { int left = _segmentLength - _activeOffset; if (length < left) { _activeOffset += length; return; } _activeOffset = 0; if (!monitorEntered) { Monitor.Enter(this, ref monitorEntered); } _first = _first !.Next; if (_first == null) { Debug.Assert(length == 0); _last = null; return; } length -= left; }while (length != 0); } finally { if (monitorEntered) { Monitor.Exit(this); } } }
private void EnsureSegmentAvailableSlow() { var seg = new Segment(this, _segmentLength); if (_last != null) { _last.Next = seg; } else { _first = seg; } _last = seg; _availableFirst ??= seg; _availableLength += _segmentLength; }
public void Clear() { var segment = _startSegment; while (segment != null) { var next = segment.Next; ReturnSegment(segment); segment = next; } // Return Sequence _startSegment = null; _endSegment = null; }
/// <summary> /// Найти самый длинный отрезок /// </summary> /// <param name="space">Набор точек</param> /// <returns>Отрезок</returns> public static Segment?MaxSegment(this IEnumerable <Point> space) { Segment?result = null; for (var i = 0; i < space.Count(); ++i) { for (var j = i + 1; j < space.Count(); ++j) { var segment = new Segment(space.ElementAt(i), space.ElementAt(j)); if (result == null || segment.Distance > result.Value.Distance) { result = segment; } } } return(result); }
private static void _AddLine(int lineKey, Segment newSegment, Dictionary <int, List <Segment> > segmentKeyToSegments) { // Get the list of segments for the given key (X for vertical lines, Y for horizontal lines) List <Segment> segments; if (!segmentKeyToSegments.TryGetValue(lineKey, out segments)) { segments = new List <Segment>(); segmentKeyToSegments[lineKey] = segments; } int isegmentInsert = 0, isegmentMergeFirst = -1, ilineSegmentLast = -1; // Find all existing segments that should be merged with the new one while (isegmentInsert < segments.Count && segments[isegmentInsert].Start <= newSegment.End) { Segment?intersectedSegment = newSegment.Intersect(segments[isegmentInsert]); if (intersectedSegment != null) { // If they overlap, merge them together, keeping track of all the existing // segments which were merged newSegment = newSegment.Union(segments[isegmentInsert]); if (isegmentMergeFirst == -1) { isegmentMergeFirst = isegmentInsert; } ilineSegmentLast = isegmentInsert; } isegmentInsert++; } if (isegmentMergeFirst == -1) { // If there was no merge, just insert the new segment segments.Insert(isegmentInsert, newSegment); } else { // If more than one segment was merged, remove all but one if (ilineSegmentLast > isegmentMergeFirst) { segments.RemoveRange(isegmentMergeFirst + 1, ilineSegmentLast - isegmentMergeFirst); } // Copy the new, merged segment back to the first original segment's slot segments[isegmentMergeFirst] = newSegment; } }
public void ConsumeTo(SequencePosition consumed) { var segment = (Segment)consumed.GetObject(); var index = consumed.GetInteger(); if (segment == _endSegment && index == _endIndex) { // keep the last page; burn anything else _startSegment !.RecycleBefore(segment); _startSegment = _endSegment; _startIndex = _endIndex = 0; } else { // discard any pages that we no longer need _startSegment !.RecycleBefore(segment); _startSegment = segment; _startIndex = index; } }
private void AddFreeSegment(Segment segment) { lock (this) { _availableLength += _segmentLength; if (_last != null) { _last.Next = segment; } else { _first = segment; } _last = segment; if (_availableFirst == null) { _availableFirst = segment; } } }
private void FixSegments(int pathIndex) { // TODO żeby nie była upośledzona Path path = Paths[pathIndex]; for (int i = 0; i < path.Segments.Count - 1; i++) { while (i < path.Segments.Count - 1 && DirectionUtils.Parallel(path.Segments[i].Direction, path.Segments[i + 1].Direction)) { Segment?merged = path.Segments[i].Merge(path.Segments[i + 1]); path.Segments.RemoveAt(i); path.Segments.RemoveAt(i); if (merged != null) { path.Segments.Insert(i, merged.Value); } else { i = Math.Max(i - 1, 0); } } } }
public CountedBuffer(int segmentLength) { _first = _last = _availableFirst = new Segment(this, segmentLength); _segmentLength = segmentLength; _availableLength = segmentLength; }
public static List <Path> FilterSelection(IEnumerable <Path> paths, bool invert = false) { var selValue = !invert; var outPaths = new List <Path>(); foreach (var path in paths) { var segments = path.Segments; IEnumerable <Segment> iter; if (!path.IsOpen && segments.First().OnCurve.IsSelected == selValue) { var segmentsList = segments.ToList(); int index; for (index = segmentsList.Count - 1; index >= 0; --index) { if (segmentsList[index].OnCurve.IsSelected != selValue) { break; } } if (index <= 0) { // All selected, bring on the original path outPaths.Add(path); continue; } else { iter = Sequence.IterAt(segmentsList, index); } } else { iter = segments; } Path outPath = null; Segment?prev = null; var prevSelected = false; foreach (var segment in iter) { var selected = segment.OnCurve.IsSelected == selValue; if (selected) { if (prevSelected) { if (invert) { // XXX: bad segment.Points.ForEach(point => point.Parent = outPath); } outPath._points.AddRange(segment.Points); } else { Point point; outPath = new Path(); if (invert) { point = segment.OnCurve; // XXX: bad. we're making assumptions about caller. // here we are reparenting because we know original paths will be trashed // (Outline.DeleteSelection) where !invert does a no copy work. // I don't like this, and the delete apis returning a list of paths tbh.... outPath.Parent = path.Parent; point.Parent = outPath; } else { point = segment.OnCurve.Clone(); } point.IsSmooth = false; point.Type = PointType.Move; outPath._points.Add(point); } } else { if (prevSelected) { if (invert) { prev.Value.OnCurve.IsSmooth = false; } // We got a path, export it and move on outPaths.Add(outPath); outPath = null; } } prev = segment; prevSelected = selected; } if (prevSelected) { outPaths.Add(outPath); } } return(outPaths); }
/// <summary> /// Given a road and a new position to add to the road, /// gets or creates a vertex to add to the road. /// The vertex will always already be added to the vertex BVH. /// If the returned vertex is null, it shouldn't be added to the road. /// If "EndRoad" is true, the road should not continue on. /// </summary> private VertexFindResults FindOrMakeVertex(Road r, Vector2 nextPos) { Vertex lastPoint = r.Points[r.Points.Count - 1]; //Reject if the segment length is too short or its position is outside the city limits. if (lastPoint.Pos.DistSqr(nextPos) <= (SegmentMinLength * SegmentMinLength) || !IsInBounds(nextPos)) { return(VertexFindResults.Reject()); } //If the next position is near another vertex, use that vertex and end the road there. foreach (Vertex v in Vertices.GetAllNearbyPos(nextPos)) { //Don't let the road loop back onto itself. if (v.RoadsConnectedTo.Contains(r)) { continue; } //Don't create a segment that already exists. if (v.VertsConnectedTo.Contains(lastPoint)) { return(VertexFindResults.Reject()); } v.ConnectTo(lastPoint); return(VertexFindResults.Accept(v, true)); } Rect segBnds = new Rect().BoundByPoints(nextPos, lastPoint.Pos); //If the segment intersects another segment, turn it into an intersection and continue. List <Segment> segs = Segments.GetAllNearbyBnds(segBnds).ToList(); float t1 = float.NaN, t2 = float.NaN; Segment?hitSeg = null; //Get any intersected segments. //If we intersect with a previous part of this road, reject. for (int i = 0; i < segs.Count; ++i) { float temp1 = float.NaN, temp2 = float.NaN; bool intersects = GeneratorUtils.SegmentsIntersect(lastPoint.Pos, nextPos, segs[i].P1.Pos, segs[i].P2.Pos, ref temp1, ref temp2); if (segs[i].Owner == r || segs[i].P1.RoadsConnectedTo.Contains(r) || segs[i].P2.RoadsConnectedTo.Contains(r)) { if (intersects) { return(VertexFindResults.Reject()); } } else if (intersects) { t1 = temp1; t2 = temp2; hitSeg = segs[i]; } } if (hitSeg.HasValue) { //Split up the road that the segment is a part of // by adding a new vertex at the intersection. Vertex vtx = new Vertex(hitSeg.Value.P1.Pos + ((hitSeg.Value.P2.Pos - hitSeg.Value.P1.Pos) * t2)); vtx.ConnectTo(lastPoint); Vertices.Add(vtx); SplitSegment(vtx, hitSeg.Value); return(VertexFindResults.Accept(vtx, false)); } //This segment isn't special in any way. Vertex vert = new Vertex(nextPos); vert.ConnectTo(lastPoint); Vertices.Add(vert); return(VertexFindResults.Accept(vert, false)); }