mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-01-31 04:40:55 +00:00
more on geometry drawing
This commit is contained in:
parent
88d1be35cc
commit
87ca45f93d
4 changed files with 108 additions and 72 deletions
|
@ -95,7 +95,7 @@
|
|||
<Compile Include="Geometry\Angle2D.cs" />
|
||||
<Compile Include="Geometry\LinedefsTracePath.cs" />
|
||||
<Compile Include="Geometry\LinedefAngleSorter.cs" />
|
||||
<Compile Include="Geometry\SectorMaker.cs" />
|
||||
<Compile Include="Geometry\SectorTools.cs" />
|
||||
<Compile Include="Geometry\Triangulator.cs" />
|
||||
<Compile Include="Geometry\EarClipVertex.cs" />
|
||||
<Compile Include="Geometry\Line2D.cs" />
|
||||
|
|
|
@ -136,7 +136,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
List<Linedef> newlines = new List<Linedef>();
|
||||
List<Vertex> mergeverts = new List<Vertex>();
|
||||
List<Vertex> nonmergeverts = new List<Vertex>(General.Map.Map.Vertices);
|
||||
|
||||
|
||||
MapSet map = General.Map.Map;
|
||||
|
||||
base.Disengage();
|
||||
|
@ -149,7 +149,9 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
// Make undo for the draw
|
||||
General.Map.UndoRedo.CreateUndo("line draw", UndoGroup.None, 0);
|
||||
|
||||
// STEP 1: Create the new geometry
|
||||
/***************************************************\
|
||||
STEP 1: Create the new geometry
|
||||
\***************************************************/
|
||||
|
||||
// Make first vertex
|
||||
Vertex v1 = map.CreateVertex((int)points[0].pos.x, (int)points[0].pos.y);
|
||||
|
@ -223,18 +225,29 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
v1 = v2;
|
||||
}
|
||||
|
||||
// STEP 2: Merge the new geometry
|
||||
/***************************************************\
|
||||
STEP 2: Merge the new geometry
|
||||
\***************************************************/
|
||||
|
||||
// Mark our new vertices that need to merge and merge them with themselves
|
||||
foreach(Vertex v in mergeverts) v.Marked = true;
|
||||
MapSet.JoinVertices(mergeverts, mergeverts, true, General.Settings.StitchDistance);
|
||||
|
||||
// Perform standard geometry stitching between new and existing geometry
|
||||
// The marked vertices indicate the new geometry
|
||||
map.StitchGeometry();
|
||||
|
||||
// Re-find our new lines, because they have been merged with the other geometry
|
||||
// Find our new lines again, because they have been merged with the other geometry
|
||||
// but their Marked property is copied where they have joined!
|
||||
newlines = map.GetMarkedLinedefs(true);
|
||||
|
||||
|
||||
// Split the new lines with the new vertices so that self-intersecting draws also work
|
||||
MapSet.SplitLinesByVertices(newlines, mergeverts, General.Settings.StitchDistance, null);
|
||||
|
||||
// STEP 3: Make sectors where possible
|
||||
/***************************************************\
|
||||
STEP 3: Join and create new sectors
|
||||
\***************************************************/
|
||||
|
||||
bool[] frontsdone = new bool[newlines.Count];
|
||||
bool[] backsdone = new bool[newlines.Count];
|
||||
for(int i = 0; i < newlines.Count; i++)
|
||||
|
@ -244,11 +257,13 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
// Front not marked as done?
|
||||
if(!frontsdone[i])
|
||||
{
|
||||
// Make sector here
|
||||
SectorMaker maker = new SectorMaker();
|
||||
Sector newsector = maker.MakeAt(ld, true);
|
||||
if(newsector != null)
|
||||
// Find a way to create a sector here
|
||||
List<LinedefSide> sectorlines = SectorTools.FindPotentialSectorAt(ld, true);
|
||||
if(sectorlines != null)
|
||||
{
|
||||
// Make the new sector
|
||||
Sector newsector = SectorTools.MakeSector(sectorlines);
|
||||
|
||||
// Go for all sidedefs in this new sector
|
||||
foreach(Sidedef sd in newsector.Sidedefs)
|
||||
{
|
||||
|
@ -269,23 +284,46 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
// Back not marked as done?
|
||||
if(!backsdone[i])
|
||||
{
|
||||
// Make sector here
|
||||
SectorMaker maker = new SectorMaker();
|
||||
Sector newsector = maker.MakeAt(ld, false);
|
||||
if(newsector != null)
|
||||
// Find a way to create a sector here
|
||||
List<LinedefSide> sectorlines = SectorTools.FindPotentialSectorAt(ld, false);
|
||||
if(sectorlines != null)
|
||||
{
|
||||
// Go for all sidedefs in this new sector
|
||||
foreach(Sidedef sd in newsector.Sidedefs)
|
||||
// We don't always want to create a new sector on the back sides
|
||||
// So first check if any of the surrounding lines originally have sidedefs
|
||||
Sidedef joinsidedef = null;
|
||||
foreach(LinedefSide ls in sectorlines)
|
||||
{
|
||||
// Side matches with a side of our new lines?
|
||||
int lineindex = newlines.IndexOf(sd.Line);
|
||||
if(lineindex > -1)
|
||||
if(ls.Front && (ls.Line.Front != null))
|
||||
{
|
||||
// Mark this side as done
|
||||
if(sd.IsFront)
|
||||
frontsdone[lineindex] = true;
|
||||
else
|
||||
backsdone[lineindex] = true;
|
||||
joinsidedef = ls.Line.Front;
|
||||
break;
|
||||
}
|
||||
else if(!ls.Front && (ls.Line.Back != null))
|
||||
{
|
||||
joinsidedef = ls.Line.Back;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Join?
|
||||
if(joinsidedef != null)
|
||||
{
|
||||
// Join the new sector
|
||||
Sector newsector = SectorTools.JoinSector(sectorlines, joinsidedef);
|
||||
|
||||
// Go for all sidedefs in this new sector
|
||||
foreach(Sidedef sd in newsector.Sidedefs)
|
||||
{
|
||||
// Side matches with a side of our new lines?
|
||||
int lineindex = newlines.IndexOf(sd.Line);
|
||||
if(lineindex > -1)
|
||||
{
|
||||
// Mark this side as done
|
||||
if(sd.IsFront)
|
||||
frontsdone[lineindex] = true;
|
||||
else
|
||||
backsdone[lineindex] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,77 +35,47 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
/// This makes a sector from all surrounding lines from a given coordinate.
|
||||
/// Automatically finds the sidedef/sector properties from surrounding sectors/sidedefs.
|
||||
/// </summary>
|
||||
public class SectorMaker
|
||||
public static class SectorTools
|
||||
{
|
||||
#region ================== Constants
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Variables
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constructor / Destructor
|
||||
#region ================== Pathfinding
|
||||
|
||||
/// <summary>
|
||||
/// This makes a sector from all surrounding lines from a given coordinate.
|
||||
/// Automatically finds the sidedef/sector properties from surrounding sectors/sidedefs.
|
||||
/// This finds a potential sector at the given coordinates,
|
||||
/// or returns null when a sector is not possible there.
|
||||
/// </summary>
|
||||
public SectorMaker()
|
||||
{
|
||||
// Initialize
|
||||
|
||||
// We have no destructor
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Methods
|
||||
|
||||
/// <summary>
|
||||
/// This makes a sector at the given coordinates, or returns null
|
||||
/// when sector could not be created.
|
||||
/// </summary>
|
||||
public Sector MakeAt(Vector2D pos)
|
||||
public static List<LinedefSide> FindPotentialSectorAt(Vector2D pos)
|
||||
{
|
||||
// Find the nearest line and determine side, then use the other method to create the sector
|
||||
Linedef l = General.Map.Map.NearestLinedef(pos);
|
||||
return MakeAt(l, (l.SideOfLine(pos) <= 0));
|
||||
return FindPotentialSectorAt(l, (l.SideOfLine(pos) <= 0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This makes a sector starting at the given line and side, or
|
||||
/// returns null when sector could not be created.
|
||||
/// This finds a potential sector starting at the given line and side,
|
||||
/// or returns null when sector is not possible.
|
||||
/// </summary>
|
||||
public Sector MakeAt(Linedef line, bool front)
|
||||
public static List<LinedefSide> FindPotentialSectorAt(Linedef line, bool front)
|
||||
{
|
||||
List<LinedefSide> alllines = new List<LinedefSide>();
|
||||
|
||||
// STEP 1: Find the outer lines
|
||||
// Find the outer lines
|
||||
Polygon p = FindOuterLines(line, front, alllines);
|
||||
if(p != null)
|
||||
{
|
||||
// STEP 2: Find the inner lines
|
||||
// Find the inner lines
|
||||
FindInnerLines(p, alllines);
|
||||
|
||||
// STEP 3: Make the sector
|
||||
return MakeSector(alllines);
|
||||
return alllines;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Pathfinding
|
||||
|
||||
// This finds the inner lines of the sector and adds them to the sector polygon
|
||||
private void FindInnerLines(Polygon p, List<LinedefSide> alllines)
|
||||
private static void FindInnerLines(Polygon p, List<LinedefSide> alllines)
|
||||
{
|
||||
Vertex foundv;
|
||||
bool vvalid, findmore;
|
||||
|
@ -206,7 +176,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
|
||||
// This finds the outer lines of the sector as a polygon
|
||||
// Returns null when no valid outer polygon can be found
|
||||
private Polygon FindOuterLines(Linedef line, bool front, List<LinedefSide> alllines)
|
||||
private static Polygon FindOuterLines(Linedef line, bool front, List<LinedefSide> alllines)
|
||||
{
|
||||
// Find inner path
|
||||
List<LinedefSide> pathlines = FindInnerMostPath(line, front);
|
||||
|
@ -233,7 +203,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
|
||||
// This finds the inner path from the beginning of a line to the end of the line.
|
||||
// Returns null when no path could be found.
|
||||
private List<LinedefSide> FindInnerMostPath(Linedef start, bool front)
|
||||
private static List<LinedefSide> FindInnerMostPath(Linedef start, bool front)
|
||||
{
|
||||
List<LinedefSide> path = new List<LinedefSide>();
|
||||
Dictionary<Linedef, int> tracecount = new Dictionary<Linedef, int>();
|
||||
|
@ -302,7 +272,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
#region ================== Sector Making
|
||||
|
||||
// This makes the sector from the given lines and sides
|
||||
private Sector MakeSector(List<LinedefSide> alllines)
|
||||
public static Sector MakeSector(List<LinedefSide> alllines)
|
||||
{
|
||||
Sidedef source = null;
|
||||
Sector newsector = General.Map.Map.CreateSector();
|
||||
|
@ -383,6 +353,34 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
return newsector;
|
||||
}
|
||||
|
||||
|
||||
// This joins a sector with the given lines and sides
|
||||
public static Sector JoinSector(List<LinedefSide> alllines, Sidedef original)
|
||||
{
|
||||
// Go for all sides to make sidedefs
|
||||
foreach(LinedefSide ls in alllines)
|
||||
{
|
||||
if(ls.Front)
|
||||
{
|
||||
// Create sidedef is needed and ensure it points to the new sector
|
||||
if(ls.Line.Front == null) General.Map.Map.CreateSidedef(ls.Line, true, original.Sector);
|
||||
original.CopyPropertiesTo(ls.Line.Front);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create sidedef is needed and ensure it points to the new sector
|
||||
if(ls.Line.Back == null) General.Map.Map.CreateSidedef(ls.Line, false, original.Sector);
|
||||
original.CopyPropertiesTo(ls.Line.Back);
|
||||
}
|
||||
|
||||
// Update line
|
||||
ls.Line.ApplySidedFlags();
|
||||
}
|
||||
|
||||
// Return the new sector
|
||||
return original.Sector;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -231,7 +231,7 @@ namespace CodeImp.DoomBuilder.Map
|
|||
if(this.selected) other.selected = true;
|
||||
if(this.marked) other.marked = true;
|
||||
|
||||
// Detach all linedefs
|
||||
// Detach all linedefs and attach them to the other
|
||||
// This will automatically dispose this vertex
|
||||
while(linedefs != null)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue