Increase performance on drawing/stitching geometry by reducing blockmap operations

This commit is contained in:
spherallic 2023-04-26 21:23:08 +02:00
parent 444aa706fb
commit 6d97c9d830
2 changed files with 51 additions and 86 deletions

View File

@ -967,11 +967,6 @@ namespace CodeImp.DoomBuilder.Geometry
List<Vertex> nonmergeverts = new List<Vertex>(General.Map.Map.Vertices);
MapSet map = General.Map.Map;
//mxd. Let's use a blockmap...
RectangleF area = MapSet.CreateArea(oldlines);
BlockMap<BlockEntry> oldlinesmap = new BlockMap<BlockEntry>(area);
oldlinesmap.AddLinedefsSet(oldlines);
General.Map.Map.ClearAllMarks(false);
// Any points to do?
@ -1116,7 +1111,7 @@ namespace CodeImp.DoomBuilder.Geometry
foreach(Linedef ld in newlines)
{
Vector2D ldcp = ld.GetCenterPoint();
Linedef nld = MapSet.NearestLinedef(oldlinesmap, ldcp); //mxd. Lines collection -> Blockmap
Linedef nld = MapSet.NearestLinedef(oldlines, ldcp); //mxd. Lines collection -> Blockmap
if(nld != null)
{
float ldside = nld.SideOfLine(ldcp);
@ -1153,7 +1148,7 @@ namespace CodeImp.DoomBuilder.Geometry
List<LinedefSide> endpoints = new List<LinedefSide>();
// Find out where the start will stitch and create test points
Linedef l1 = MapSet.NearestLinedefRange(oldlinesmap, firstline.Start.Position, MapSet.STITCH_DISTANCE); //mxd. Lines collection -> Blockmap
Linedef l1 = MapSet.NearestLinedefRange(oldlines, firstline.Start.Position, MapSet.STITCH_DISTANCE); //mxd. Lines collection -> Blockmap
Vertex vv1 = null;
if(l1 != null)
{
@ -1178,7 +1173,7 @@ namespace CodeImp.DoomBuilder.Geometry
}
// Find out where the end will stitch and create test points
Linedef l2 = MapSet.NearestLinedefRange(oldlinesmap, lastline.End.Position, MapSet.STITCH_DISTANCE); //mxd. Lines collection -> Blockmap
Linedef l2 = MapSet.NearestLinedefRange(oldlines, lastline.End.Position, MapSet.STITCH_DISTANCE); //mxd. Lines collection -> Blockmap
Vertex vv2 = null;
if(l2 != null)
{

View File

@ -2079,18 +2079,18 @@ namespace CodeImp.DoomBuilder.Map
// Find vertices
HashSet<Vertex> movingverts = new HashSet<Vertex>(General.Map.Map.GetMarkedVertices(true));
HashSet<Vertex> fixedverts = new HashSet<Vertex>(General.Map.Map.GetMarkedVertices(false));
// Find lines that moved during the drag
HashSet<Linedef> movinglines = new HashSet<Linedef>(LinedefsFromMarkedVertices(false, true, true));
// Find all non-moving lines
HashSet<Linedef> fixedlines = new HashSet<Linedef>(LinedefsFromMarkedVertices(true, false, false));
// Determine area in which we are editing
RectangleF editarea = CreateArea(movinglines);
editarea = IncreaseArea(editarea, movingverts);
editarea.Inflate(1.0f, 1.0f);
// Join nearby vertices
BeginAddRemove();
JoinVertices(fixedverts, movingverts, true, STITCH_DISTANCE);
@ -2100,23 +2100,24 @@ namespace CodeImp.DoomBuilder.Map
Update(true, false);
BeginAddRemove();
// Split moving lines with unselected vertices
ICollection<Vertex> nearbyfixedverts = FilterByArea(fixedverts, ref editarea);
if(!SplitLinesByVertices(movinglines, nearbyfixedverts, STITCH_DISTANCE, movinglines, mergemode))
return false;
// Split non-moving lines with selected vertices
fixedlines = new HashSet<Linedef>(fixedlines.Where(fixedline => !fixedline.IsDisposed));
// Split non-moving lines with selected vertices
fixedlines = FilterByArea(fixedlines, ref editarea);
fixedlines = new HashSet<Linedef>(fixedlines.Where(fixedline => !fixedline.IsDisposed));
if(!SplitLinesByVertices(fixedlines, movingverts, STITCH_DISTANCE, movinglines, mergemode))
return false;
//mxd. Split moving lines with fixed lines
if(!SplitLinesByLines(fixedlines, movinglines, mergemode)) return false;
// Remove looped linedefs
RemoveLoopedLinedefs(movinglines);
// Join overlapping lines
if(!JoinOverlappingLines(movinglines)) return false;
@ -2186,7 +2187,7 @@ namespace CodeImp.DoomBuilder.Map
{
FlipBackwardLinedefs(changedlines);
}
return true;
}
@ -2792,87 +2793,55 @@ namespace CodeImp.DoomBuilder.Map
do
{
//mxd. Create blockmap
ICollection<Vertex> biggerset, smallerset;
bool keepsmaller;
if(set1.Count > set2.Count)
{
biggerset = set1;
smallerset = set2;
keepsmaller = !keepsecond;
}
else
{
biggerset = set2;
smallerset = set1;
keepsmaller = keepsecond;
}
RectangleF area = CreateArea(biggerset);
BlockMap<BlockEntry> blockmap = new BlockMap<BlockEntry>(area);
blockmap.AddVerticesSet(biggerset);
// No joins yet
joined = false;
// Go for all vertices in the smaller set
foreach(Vertex v1 in smallerset)
// Go for all vertices in the first set
foreach (Vertex v1 in set1)
{
HashSet<BlockEntry> blocks = new HashSet<BlockEntry>
// Go for all vertices in the second set
foreach (Vertex v2 in set2)
{
blockmap.GetBlockAt(v1.Position),
blockmap.GetBlockAt(new Vector2D(v1.Position.x + joindist, v1.Position.y + joindist)),
blockmap.GetBlockAt(new Vector2D(v1.Position.x + joindist, v1.Position.y - joindist)),
blockmap.GetBlockAt(new Vector2D(v1.Position.x - joindist, v1.Position.y + joindist)),
blockmap.GetBlockAt(new Vector2D(v1.Position.x - joindist, v1.Position.y - joindist))
};
foreach(BlockEntry be in blocks)
{
if(be == null) continue;
foreach(Vertex v2 in be.Vertices)
// Check if vertices are close enough
if (v1.DistanceToSq(v2.Position) <= joindist2)
{
// Check if vertices are close enough
if(v1.DistanceToSq(v2.Position) <= joindist2)
// Check if not the same vertex
if (v1 != v2)
{
// Check if not the same vertex
if(v1 != v2)
// Move the second vertex to match the first
v2.Move(v1.Position);
// Check which one to keep
if (keepsecond)
{
// Move the second vertex to match the first
v2.Move(v1.Position);
// Check which one to keep
if(keepsmaller)
{
// Join the first into the second
// Second is kept, first is removed
v1.Join(v2);
biggerset.Remove(v1);
smallerset.Remove(v1);
}
else
{
// Join the second into the first
// First is kept, second is removed
v2.Join(v1);
biggerset.Remove(v2);
smallerset.Remove(v2);
}
// Count the join
joinsdone++;
joined = true;
break;
// Join the first into the second
// Second is kept, first is removed
v1.Join(v2);
set1.Remove(v1);
set2.Remove(v1);
}
else
{
// Join the second into the first
// First is kept, second is removed
v2.Join(v1);
set1.Remove(v2);
set2.Remove(v2);
}
// Count the join
joinsdone++;
joined = true;
break;
}
}
}
// Will have to restart when joined
if(joined) break;
if (joined) break;
}
}
while(joined);
while (joined);
// Return result
return joinsdone;
@ -2959,6 +2928,7 @@ namespace CodeImp.DoomBuilder.Map
//mxd. Create blockmap
RectangleF area = CreateArea(lines);
IncreaseArea(area, verts);
General.WriteLogLine("Area = " + area.Width + ", " + area.Height);
BlockMap<BlockEntry> blockmap = new BlockMap<BlockEntry>(area);
blockmap.AddVerticesSet(verts);
blockmap.AddLinedefsSet(lines);
@ -3079,10 +3049,10 @@ namespace CodeImp.DoomBuilder.Map
}
}
// [ZZ] note: disposing a vertex means also disposing all attached linedefs!
// we need to iterate through our lines collection and make sure no disposed linedefs exist there.
// also, just in case, do it for vertices as well, because vertices can be chain-disposed.
foreach (Linedef line in lines.Where(line => line.IsDisposed).ToList())
// [ZZ] note: disposing a vertex means also disposing all attached linedefs!
// we need to iterate through our lines collection and make sure no disposed linedefs exist there.
// also, just in case, do it for vertices as well, because vertices can be chain-disposed.
foreach (Linedef line in lines.Where(line => line.IsDisposed).ToList())
while (lines.Remove(line));
foreach (Vertex vert in verts.Where(vert => vert.IsDisposed).ToList())
while (verts.Remove(vert));