2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #ifndef _OBJECT_POS_SELECTOR_H
20 #define _OBJECT_POS_SELECTOR_H
26 enum UsedPosType
{ USED_POS_PLUS
, USED_POS_MINUS
};
28 inline UsedPosType
operator ~(UsedPosType uptype
)
30 return uptype
==USED_POS_PLUS
? USED_POS_MINUS
: USED_POS_PLUS
;
33 struct ObjectPosSelector
37 UsedPos(float sign_
, float size_
,float dist_
) : sign(sign_
), size(size_
),dist(dist_
) {}
41 float size
; // size of point
42 float dist
; // dist to central point (including central point size)
45 typedef std::multimap
<float,UsedPos
> UsedPosList
; // abs(angle)->Node
47 ObjectPosSelector(float x
,float y
,float size
,float dist
);
49 void AddUsedPos(float size
,float angle
,float dist
);
50 void InitializeAngle();
52 bool FirstAngle(float& angle
);
53 bool NextAngle(float& angle
);
54 bool NextUsedAngle(float& angle
);
56 bool NextPosibleAngle( float& angle
);
58 bool CheckAngle(UsedPosList::value_type
const& nextUsedPos
, float sign
, float angle
) const
60 float angle_step2
= GetAngle(nextUsedPos
.second
);
62 float next_angle
= nextUsedPos
.first
;
63 if(nextUsedPos
.second
.sign
* sign
< 0) // last node from diff. list (-pi+alpha)
64 next_angle
= 2*M_PI
-next_angle
; // move to positive
66 return fabs(angle
)+angle_step2
<= next_angle
;
69 bool CheckOriginal() const
71 return (m_UsedPosLists
[USED_POS_PLUS
].empty() || CheckAngle( *m_UsedPosLists
[USED_POS_PLUS
].begin(),1.0,0)) &&
72 (m_UsedPosLists
[USED_POS_MINUS
].empty() || CheckAngle( *m_UsedPosLists
[USED_POS_MINUS
].begin(),-1.0,0));
75 bool IsNonBalanced() const { return m_UsedPosLists
[USED_POS_PLUS
].empty() != m_UsedPosLists
[USED_POS_MINUS
].empty(); }
77 bool NextAngleFor( UsedPosList::value_type
const& usedPos
, float sign
, UsedPosType uptype
, float &angle
)
79 float angle_step
= GetAngle(usedPos
.second
);
81 // next possible angle
82 angle
= usedPos
.first
* usedPos
.second
.sign
+ angle_step
* sign
;
84 UsedPosList::value_type
const* nextNode
= nextUsedPos(uptype
);
87 // if next node permit use selected angle, then do it
88 if(!CheckAngle(*nextNode
, sign
, angle
))
90 m_smallStepOk
[uptype
] = false;
95 // possible more points
96 m_smallStepOk
[uptype
] = true;
97 m_smallStepAngle
[uptype
] = angle
;
98 m_smallStepNextUsedPos
[uptype
] = nextNode
;
103 bool NextSmallStepAngle( float sign
, UsedPosType uptype
, float &angle
)
105 // next possible angle
106 angle
= m_smallStepAngle
[uptype
] + m_anglestep
* sign
;
108 if(fabs(angle
) > M_PI
)
110 m_smallStepOk
[uptype
] = false;
114 if(m_smallStepNextUsedPos
[uptype
])
116 if(fabs(angle
) >= m_smallStepNextUsedPos
[uptype
]->first
)
118 m_smallStepOk
[uptype
] = false;
122 // if next node permit use selected angle, then do it
123 if(!CheckAngle(*m_smallStepNextUsedPos
[uptype
], sign
, angle
))
125 m_smallStepOk
[uptype
] = false;
130 // possible more points
131 m_smallStepAngle
[uptype
] = angle
;
135 // next used post for m_nextUsedPos[uptype]
136 UsedPosList::value_type
const* nextUsedPos(UsedPosType uptype
);
138 // angle from used pos to next possible free pos
139 float GetAngle(UsedPos
const& usedPos
) const { return acos(m_dist
/(usedPos
.dist
+usedPos
.size
+m_size
)); }
143 float m_size
; // size of object in center
144 float m_dist
; // distance for searching pos (including central object size)
147 UsedPosList m_UsedPosLists
[2];
148 UsedPosList::const_iterator m_nextUsedPos
[2];
150 // field for small step from first after next used pos until next pos
151 float m_smallStepAngle
[2];
152 bool m_smallStepOk
[2];
153 UsedPosList::value_type
const* m_smallStepNextUsedPos
[2];