diff --git a/Source/Core/Map/Sector.cs b/Source/Core/Map/Sector.cs index 8047f5d64f432f63b74d86b28ae45b27426cbc42..7ad3d227ee34e596d227e7cc2ee8a436a1ed54a7 100755 --- a/Source/Core/Map/Sector.cs +++ b/Source/Core/Map/Sector.cs @@ -546,6 +546,9 @@ namespace CodeImp.DoomBuilder.Map // This checks if the given point is inside the sector polygon // See: http://paulbourke.net/geometry/polygonmesh/index.html#insidepoly + // This checks for the linedefs instead of the sidedefs, since self-referencing sectors + // will never result in an odd number of intersections when using sidedefs, since both + // sidedefs of the outer linedef belong to the same sector public bool Intersect(Vector2D p) { return Intersect(p, true); } public bool Intersect(Vector2D p, bool countontopastrue) { @@ -554,13 +557,17 @@ namespace CodeImp.DoomBuilder.Map uint c = 0; Vector2D v1, v2; + HashSet<Linedef> linedefs = new HashSet<Linedef>(sidedefs.Count); + + foreach (Sidedef sd in sidedefs) + linedefs.Add(sd.Line); - // Go for all sidedefs - foreach(Sidedef sd in sidedefs) + // Go for all linedefs + foreach(Linedef ld in linedefs) { // Get vertices - v1 = sd.Line.Start.Position; - v2 = sd.Line.End.Position; + v1 = ld.Start.Position; + v2 = ld.End.Position; //mxd. On top of a vertex? if(p == v1 || p == v2) return countontopastrue; diff --git a/Source/Core/Map/Thing.cs b/Source/Core/Map/Thing.cs index 23e44224c4f826a3ce1b08b8878cf3b395083a78..7105fb4cda03cefe10e5d749d4fa6924062071df 100755 --- a/Source/Core/Map/Thing.cs +++ b/Source/Core/Map/Thing.cs @@ -273,19 +273,46 @@ namespace CodeImp.DoomBuilder.Map public void DetermineSector(BlockMap<BlockEntry> blockmap) { BlockEntry be = blockmap.GetBlockAt(pos); + List<Sector> sectors = new List<Sector>(1); foreach (Sector s in be.Sectors) if (s.Intersect(pos)) - { - sector = s; - return; - } + sectors.Add(s); + + if(sectors.Count == 0) + { + sector = null; + } + if (sectors.Count == 1) + { + sector = sectors[0]; + } + else + { + // Having multiple intersections indicates that there are self-referencing sectors in this spot. + // In this case we have to check which side of the nearest linedef pos is on, and then use that sector + HashSet<Linedef> linedefs = new HashSet<Linedef>(sectors[0].Sidedefs.Count * sectors.Count); + + foreach (Sector s in sectors) + foreach (Sidedef sd in s.Sidedefs) + linedefs.Add(sd.Line); + + Linedef nearest = MapSet.NearestLinedef(linedefs, pos); + double d = nearest.SideOfLine(pos); + + if (d <= 0.0 && nearest.Front != null) + sector = nearest.Front.Sector; + else if (nearest.Back != null) + sector = nearest.Back.Sector; + else + sector = null; + } } // This determines which sector the thing is in and links it public void DetermineSector(VisualBlockMap blockmap) { - sector = blockmap.GetSectorAt(pos); + sector = blockmap.GetSectorAt(pos); } // This translates the flags into UDMF fields diff --git a/Source/Core/VisualModes/VisualBlockMap.cs b/Source/Core/VisualModes/VisualBlockMap.cs index 9a985921a217e0ce4af60a20343d7cc6e6917b35..5a4c9641b42b0758084e3455fdb868081966d1ba 100755 --- a/Source/Core/VisualModes/VisualBlockMap.cs +++ b/Source/Core/VisualModes/VisualBlockMap.cs @@ -76,16 +76,40 @@ namespace CodeImp.DoomBuilder.VisualModes public Sector GetSectorAt(Vector2D pos) { - foreach (VisualBlockEntry e in GetBlocks(pos)) - { + List<Sector> sectors = new List<Sector>(1); + + foreach (VisualBlockEntry e in GetBlocks(pos)) foreach (Sector s in e.Sectors) - { if (s.Intersect(pos)) - { - return s; - } - } - } + sectors.Add(s); + + if (sectors.Count == 0) + { + return null; + } + else if (sectors.Count == 1) + { + return sectors[0]; + } + else + { + // Having multiple intersections indicates that there are self-referencing sectors in this spot. + // In this case we have to check which side of the nearest linedef pos is on, and then use that sector + HashSet<Linedef> linedefs = new HashSet<Linedef>(sectors[0].Sidedefs.Count * sectors.Count); + + foreach (Sector s in sectors) + foreach (Sidedef sd in s.Sidedefs) + linedefs.Add(sd.Line); + + Linedef nearest = MapSet.NearestLinedef(linedefs, pos); + double d = nearest.SideOfLine(pos); + + if (d <= 0.0 && nearest.Front != null) + return nearest.Front.Sector; + else if (nearest.Back != null) + return nearest.Back.Sector; + } + return null; }