1 /*
2  *	l_super.h - Superimposed_ld class
3  *	AYM 2003-12-02
4  */
5 
6 /*
7 This file is copyright Andr� Majorel 2003.
8 
9 This program is free software; you can redistribute it and/or modify it under
10 the terms of version 2 of the GNU General Public License as published by the
11 Free Software Foundation.
12 
13 This program is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License along with
18 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 Place, Suite 330, Boston, MA 02111-1307, USA.
20 */
21 
22 
23 #ifndef YH_L_SUPER  /* DO NOT INSERT ANYTHING BEFORE THIS LINE */
24 #define YH_L_SUPER
25 
26 #include "levels.h"
27 #include "objid.h"
28 
29 
30 /* The Superimposed_ld class is used to find all the linedefs that are
31    superimposed with a particular reference linedef. Call the set()
32    method to specify the reference linedef. Each call to the get()
33    method returns the number of the next superimposed linedef, or -1
34    when there are no more superimposed linedefs.
35 
36    Two linedefs are superimposed iff their ends have the same map
37    coordinates, regardless of whether the vertex numbers are the same,
38    and irrespective of start/end vertex distinctions. */
39 
40 class Superimposed_ld
41 {
42   public:
43              Superimposed_ld ();
44     int      set             (obj_no_t);
45     obj_no_t get             ();
46     void     rewind          ();
47 
48   private:
49     obj_no_t refldno;			// Reference linedef
50     obj_no_t ldno;			// get() will start from there
51 };
52 
53 
Superimposed_ld()54 inline Superimposed_ld::Superimposed_ld ()
55 {
56   refldno = -1;
57   rewind ();
58 }
59 
60 
61 /*
62  *	Superimposed_ld::set - set the reference linedef
63  *
64  *	If the argument is not a valid linedef number, does nothing and
65  *	returns a non-zero value. Otherwise, set the linedef number,
66  *	calls rewind() and returns a zero value.
67  */
set(obj_no_t ldno)68 inline int Superimposed_ld::set (obj_no_t ldno)
69 {
70   if (! is_linedef (ldno))		// Paranoia
71     return 1;
72 
73   refldno = ldno;
74   rewind ();
75   return 0;
76 }
77 
78 
79 /*
80  *	Superimposed_ld::get - return the next superimposed linedef
81  *
82  *	Returns the number of the next superimposed linedef, or -1 if
83  *	there's none. If the reference linedef was not specified, or is
84  *	invalid (possibly as a result of changes in the level), returns
85  *	-1.
86  *
87  *	Linedefs that have invalid start/end vertices are silently
88  *	skipped.
89  */
get()90 inline obj_no_t Superimposed_ld::get ()
91 {
92   if (refldno == -1)
93     return -1;
94 
95   /* These variables are there to speed things up a bit by avoiding
96      repetitive table lookups. Everything is re-computed each time as
97      LineDefs could very well be realloc'd while we were out. */
98 
99   if (! is_linedef (refldno))
100     return -1;
101   const struct LineDef *const pmax = LineDefs + NumLineDefs;
102   const struct LineDef *const pref = LineDefs + refldno;
103 
104   const wad_vn_t refv0 = pref->start;
105   const wad_vn_t refv1 = pref->end;
106   if (! is_vertex (refv0) || ! is_vertex (refv1))		// Paranoia
107     return -1;
108 
109   const wad_coord_t refx0 = Vertices[refv0].x;
110   const wad_coord_t refy0 = Vertices[refv0].y;
111   const wad_coord_t refx1 = Vertices[refv1].x;
112   const wad_coord_t refy1 = Vertices[refv1].y;
113 
114   for (const struct LineDef *p = LineDefs + ldno; ldno < NumLineDefs;
115       p++, ldno++)
116   {
117     if (! is_vertex (p->start) || ! is_vertex (p->end))		// Paranoia
118       continue;
119     obj_no_t x0 = Vertices[p->start].x;
120     obj_no_t y0 = Vertices[p->start].y;
121     obj_no_t x1 = Vertices[p->end].x;
122     obj_no_t y1 = Vertices[p->end].y;
123     if ( x0 == refx0 && y0 == refy0 && x1 == refx1 && y1 == refy1
124       || x0 == refx1 && y0 == refy1 && x1 == refx0 && y1 == refy0)
125     {
126       if (ldno == refldno)
127 	continue;
128       return ldno++;
129     }
130   }
131 
132   return -1;
133 }
134 
135 
136 /*
137  *	Superimposed_ld::rewind - rewind the counter
138  *
139  *	After calling this method, the next call to get() will start
140  *	from the first linedef.
141  */
rewind()142 inline void Superimposed_ld::rewind ()
143 {
144   ldno = 0;
145 }
146 
147 
148 #endif  /* DO NOT ADD ANYTHING AFTER THIS LINE */
149