OpenStructure
Loading...
Searching...
No Matches
spatial_organizer.hh
Go to the documentation of this file.
1//------------------------------------------------------------------------------
2// This file is part of the OpenStructure project <www.openstructure.org>
3//
4// Copyright (C) 2008-2020 by the OpenStructure authors
5//
6// This library is free software; you can redistribute it and/or modify it under
7// the terms of the GNU Lesser General Public License as published by the Free
8// Software Foundation; either version 3.0 of the License, or (at your option)
9// any later version.
10// This library is distributed in the hope that it will be useful, but WITHOUT
11// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13// details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with this library; if not, write to the Free Software Foundation, Inc.,
17// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18//------------------------------------------------------------------------------
19#ifndef OST_SPATIAL_ORGANIZER_HI
20#define OST_SPATIAL_ORGANIZER_HI
21
22#include <vector>
23#include <map>
24#include <cmath>
25#include <limits>
26
27#include <ost/geom/geom.hh>
28
29namespace ost { namespace mol {
30
32/*
33 organizes ITEMs defined by positions
34 in a spatial hash map, into bins of
35 a defined size (as given in the ctor)
36*/
37template <class ITEM, class VEC=geom::Vec3>
39public:
40 typedef std::vector<ITEM> ItemList;
41
42private:
43 struct Index {
44 Index():
45 u(0),v(0),w(0) {}
46 Index(int uu, int vv, int ww):
47 u(uu),v(vv),w(ww) {}
48
49 bool operator<(const Index& other) const {
50 return w!=other.w ? w<other.w : (v!=other.v ? v<other.v : u<other.u);
51 }
52
53 int u,v,w;
54
55 static Index Max(const Index& a, const Index& b) {
56 Index m;
57 m.u = a.u > b.u ? a.u : b.u;
58 m.v = a.v > b.v ? a.v : b.v;
59 m.w = a.w > b.w ? a.w : b.w;
60 return m;
61 }
62
63 static Index Min(const Index& a, const Index& b) {
64 Index m;
65 m.u = a.u < b.u ? a.u : b.u;
66 m.v = a.v < b.v ? a.v : b.v;
67 m.w = a.w < b.w ? a.w : b.w;
68 return m;
69 }
70
71 };
72
73 struct Entry {
74 Entry(const ITEM& i, const VEC& p): item(i), pos(p) {}
75
76 ITEM item;
77 VEC pos;
78 };
79
80 typedef std::vector<Entry> EntryList;
81
82 typedef std::map<Index,EntryList> ItemMap;
83
84public:
85
86 SpatialOrganizer(Real delta): delta_(delta) {
87 if(delta==0.0) {
88 throw "delta cannot be zero";
89 }
90 }
91
92 void Add(const ITEM& item, const VEC& pos) {
93 bool first = map_.empty();
94 Index indx=gen_index(pos);
95 map_[indx].push_back(Entry(item,pos));
96 if (!first) {
97 min_ = Index::Min(min_, indx);
98 max_ = Index::Max(max_, indx);
99 } else {
100 min_ = indx;
101 max_ = indx;
102 }
103 }
104 void Remove(const ITEM& item) {
105 typename ItemMap::iterator i=map_.begin();
106 for (; i!=map_.end(); ++i) {
107 for (size_t j=0; j<i->second.size(); ++j) {
108 if (i->second[j].item==item) {
109 i->second.erase(i->second.begin()+j);
110 return;
111 }
112 }
113 }
114 }
115
116 void Remove(const ITEM& item, const VEC& pos) {
117 // variation of the above, first try in organizer bucket
118 // for which you give a hint with pos. If this is successful,
119 // return. Call naive Remove otherwise
120 Index indx=gen_index(pos);
121 typename ItemMap::iterator i = map_.find(indx);
122 if(i != map_.end()) {
123 for (size_t j=0; j<i->second.size(); ++j) {
124 if (i->second[j].item==item) {
125 i->second.erase(i->second.begin()+j);
126 return;
127 }
128 }
129 }
130 Remove(item);
131 }
132
133 bool HasWithin(const VEC& pos, Real dist) const {
134 Real dist2=dist*dist;
135 Index imin = Index::Max(min_, gen_index(pos-VEC(dist,dist,dist)));
136 Index imax = Index::Min(max_, gen_index(pos+VEC(dist,dist,dist)));
137 const size_t tmp = (imax.u-imin.u+1)*(imax.v-imin.v+1)*(imax.w-imin.w+1);
138 if (tmp > map_.size()) {
139 return this->has_within_all_buckets(pos, dist2);
140 }
141 for(int wc=imin.w;wc<=imax.w;++wc) {
142 for(int vc=imin.v;vc<=imax.v;++vc) {
143 for(int uc=imin.u;uc<=imax.u;++uc) {
144 typename ItemMap::const_iterator map_it = map_.find(Index(uc,vc,wc));
145 if(map_it!=map_.end()) {
146 for(typename EntryList::const_iterator entry_it = map_it->second.begin();
147 entry_it != map_it->second.end(); ++entry_it) {
148 /*
149 speed tests indicate that pre-calculating dx2 or dy2
150 and pre-checking them with an additional if gives little
151 speed improvement for very specific circumstances only,
152 but most of the time the performance is worse.
153 */
154 Real delta_x = entry_it->pos[0]-pos[0];
155 Real delta_y = entry_it->pos[1]-pos[1];
156 Real delta_z = entry_it->pos[2]-pos[2];
157 if(delta_x*delta_x+delta_y*delta_y+delta_z*delta_z<=dist2) {
158 return true;
159 }
160 }
161 }
162 }
163 }
164 }
165 return false;
166 }
167
168 ItemList FindWithin(const VEC& pos, Real dist) const {
169 Real dist2=dist*dist;
170 Index imin = gen_index(pos-VEC(dist,dist,dist));
171 Index imax = gen_index(pos+VEC(dist,dist,dist));
172
173 ItemList item_list;
174
175 for(int wc=imin.w;wc<=imax.w;++wc) {
176 for(int vc=imin.v;vc<=imax.v;++vc) {
177 for(int uc=imin.u;uc<=imax.u;++uc) {
178 typename ItemMap::const_iterator map_it = map_.find(Index(uc,vc,wc));
179
180 if(map_it!=map_.end()) {
181 for(typename EntryList::const_iterator entry_it = map_it->second.begin();
182 entry_it != map_it->second.end(); ++entry_it) {
183 /*
184 speed tests indicate that pre-calculating dx2 or dy2
185 and pre-checking them with an additional if gives little
186 speed improvement for very specific circumstances only,
187 but most of the time the performance is worse.
188 */
189 Real delta_x = entry_it->pos[0]-pos[0];
190 Real delta_y = entry_it->pos[1]-pos[1];
191 Real delta_z = entry_it->pos[2]-pos[2];
192 if(delta_x*delta_x+delta_y*delta_y+delta_z*delta_z<=dist2) {
193 item_list.push_back(entry_it->item);
194 }
195 }
196 }
197 }
198 }
199 }
200 return item_list;
201 }
202 void Clear()
203 {
204 map_.clear();
205 }
207 map_.swap(o.map_);
208 std::swap(delta_,o.delta_);
209 std::swap(min_, o.min_);
210 std::swap(max_, o.max_);
211 }
212
213private:
214 bool has_within_all_buckets(const VEC& pos, Real dist2) const {
215 for (typename ItemMap::const_iterator
216 i = map_.begin(), e = map_.end(); i!=e; ++i) {
217 for(typename EntryList::const_iterator j = i->second.begin();
218 j != i->second.end(); ++j) {
219 Real delta_x = j->pos[0]-pos[0];
220 Real delta_y = j->pos[1]-pos[1];
221 Real delta_z = j->pos[2]-pos[2];
222 if(delta_x*delta_x+delta_y*delta_y+delta_z*delta_z<=dist2) {
223 return true;
224 }
225 }
226 }
227 return false;
228 }
229 ItemMap map_;
230 Real delta_;
231 Index min_;
232 Index max_;
233
234 Index gen_index(const VEC& pos) const {
235 Index nrvo(static_cast<int>(round(pos[0]/delta_)),
236 static_cast<int>(round(pos[1]/delta_)),
237 static_cast<int>(round(pos[2]/delta_)));
238 return nrvo;
239 }
240
241 geom::Vec3 gen_middle(const Index& i) const {
242 geom::Vec3 nrvo((static_cast<Real>(i.u)+0.5)*delta_,
243 (static_cast<Real>(i.v)+0.5)*delta_,
244 (static_cast<Real>(i.w)+0.5)*delta_);
245 return nrvo;
246 }
247
248};
249
250}} // ns
251
252#endif
Three dimensional vector class, using Real precision.
Definition vec3.hh:48
ItemList FindWithin(const VEC &pos, Real dist) const
void Remove(const ITEM &item, const VEC &pos)
void Add(const ITEM &item, const VEC &pos)
void Remove(const ITEM &item)
void Swap(SpatialOrganizer &o)
bool HasWithin(const VEC &pos, Real dist) const
float Real
Definition base.hh:44
#define DLLEXPORT_OST_MOL
bool operator<(const ResidueHandle &lhs, const ResidueHandle &rhs)
Definition base.dox:1