2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * @author Tristan Roussillon (\c tristan.roussillon@liris.cnrs.fr )
20 * Laboratoire d'InfoRmatique en Image et Systemes d'information - LIRIS (CNRS, UMR 5205), CNRS, France
24 * Implementation of inline methods defined in PlaneProbingLNeighborhood.h
26 * This file is part of the DGtal library.
30 //////////////////////////////////////////////////////////////////////////////
32 //////////////////////////////////////////////////////////////////////////////
35 ///////////////////////////////////////////////////////////////////////////////
36 // IMPLEMENTATION of inline methods.
37 ///////////////////////////////////////////////////////////////////////////////
39 ///////////////////////////////////////////////////////////////////////////////
40 // ----------------------- Standard services ------------------------------
42 // ------------------------------------------------------------------------
43 template < typename TPredicate >
45 DGtal::PlaneProbingLNeighborhood<TPredicate>::
46 PlaneProbingLNeighborhood(Predicate const& aPredicate, Point const& aQ, Triangle const& aM)
47 : DGtal::PlaneProbingRNeighborhood<TPredicate>(aPredicate, aQ, aM)
49 for (int k = 0; k < 3; k++) {
50 myGrids.push_back(closestInGrid(k));
54 // ------------------------------------------------------------------------
55 template < typename TPredicate >
57 DGtal::PlaneProbingLNeighborhood<TPredicate>::~PlaneProbingLNeighborhood()
60 ///////////////////////////////////////////////////////////////////////////////
61 // ----------------------- Plane Probing services ------------------------------
63 // ------------------------------------------------------------------------
64 template < typename TPredicate >
66 typename DGtal::PlaneProbingLNeighborhood<TPredicate>::HexagonState
67 DGtal::PlaneProbingLNeighborhood<TPredicate>::hexagonState ()
69 for (int k = 0; k < 3; k++) {
73 std::array<bool, 6> state({ false, false, false, false, false, false });
74 for (int k = 0; k < 3; k++) {
75 state[2*k] = myGrids[k].myPair.first;
76 state[2*k+1] = myGrids[k].myPair.second;
79 return this->classify(state);
82 // ------------------------------------------------------------------------
83 template < typename TPredicate >
85 typename DGtal::PlaneProbingLNeighborhood<TPredicate>::UpdateOperation
86 DGtal::PlaneProbingLNeighborhood<TPredicate>::
90 std::vector<GridPoint> validGridPoints;
91 for (int k = 0; k < 3; k++) {
92 GridPoint gp = myGrids[k].myGridPoint;
94 validGridPoints.push_back(gp);
97 if (validGridPoints.size() == 1) {
99 return getOperationFromGridPoint(validGridPoints[0]);
102 // One should call hexagonState before closestCandidate, and check the return value
103 // to ensure that there is at least one point in the plane in the H-neighbhorhood
104 ASSERT(validGridPoints.size() == 2);
106 if (this->isSmallest(this->relativePoint(validGridPoints[0]),
107 this->relativePoint(validGridPoints[1]))) {
108 return getOperationFromGridPoint(validGridPoints[1]);
110 return getOperationFromGridPoint(validGridPoints[0]);
116 ///////////////////////////////////////////////////////////////////////////////
117 // ----------------------- Helpers to find a closest point ----------------
119 // ------------------------------------------------------------------------
120 template < typename TPredicate >
122 typename DGtal::PlaneProbingLNeighborhood<TPredicate>::ClosestGridPoint
123 DGtal::PlaneProbingLNeighborhood<TPredicate>::
124 closestInGrid (const Index& aIdx) const
126 std::vector<GridPoint> candidates;
129 GridPoint y1(1,0,k); //y1 = vk + m1
130 GridPoint y2(0,1,k); //y2 = vk + m2
132 if (this->myPredicate(this->absolutePoint(y1))) {
133 if (this->myPredicate(this->absolutePoint(y2))) {
134 //at least 2 candidates
135 if (this->isSmallest(this->relativePoint(y1), this->relativePoint(y2))) {
136 candidates.push_back(y2);
138 candidates.push_back(y1);
141 ASSERT(candidates.size() == 1);
142 candidatesInGrid(y1, y2, std::back_inserter(candidates));
143 GridPoint closest = this->closestPointInList(candidates);
144 return ClosestGridPoint( closest, true, true );
148 return ClosestGridPoint( y1, true, false );
151 if (this->myPredicate(this->absolutePoint(y2))) {
153 return ClosestGridPoint( y2, false, true );
156 return ClosestGridPoint( GridPoint(0, 0, k), false, false );
161 // ------------------------------------------------------------------------
162 template < typename TPredicate >
165 DGtal::PlaneProbingLNeighborhood<TPredicate>::
166 candidatesInGrid (const GridPoint& y1, const GridPoint& y2,
167 std::back_insert_iterator<std::vector<GridPoint> > out) const
169 using DGtal::detail::squaredNorm;
171 ASSERT( (this->myPredicate(this->absolutePoint(y1)) &&
172 (this->myPredicate(this->absolutePoint(y2)))) );
174 Integer a = direction(y1).dot(direction(y2));
177 GridPoint y = y1 + y2;
178 Integer a1 = direction(y1).dot(direction(y));
179 Integer a2 = direction(y2).dot(direction(y));
180 if ( (a1 < 0)||(a2 < 0) ) {
188 ASSERT(squaredNorm(direction(u)) > squaredNorm(direction(w)));
190 Integer gamma = (-a)/squaredNorm(direction(w));
191 GridPoint w2 = u + w*gamma;
192 GridPoint w2Next = u + w*(gamma+1);
194 if (direction(w2).dot(direction(w2Next)) < 0) {
196 if (this->myPredicate(this->absolutePoint(w2))) {
197 candidatesInGrid(w, w2, out);
199 //we look for a closest point on the ray u +cw, c<gamma
200 GridPointOnProbingRay gr = closestOnBoundedRayLogWithPredicate(GridPointOnProbingRay(u,w.direction()),gamma);
201 ASSERT( gr == closestOnBoundedRayLinearWithPredicate(GridPointOnProbingRay(u,w.direction()),gamma) );
202 *out++ = gr.gridPoint();
205 //excepted the first one, the other angles along
206 // the ray are all acute (or right),
207 ASSERT( direction(w2).dot(direction(w2Next)) >= 0 );
208 ASSERT( direction(w).dot(direction(w2Next)) >= 0 );
210 //whatever w2Next is in plane or not,
211 //we look for a closest point on the ray u +cw, c<=gamma+1
212 GridPointOnProbingRay gr = closestOnBoundedRayLogWithPredicate(GridPointOnProbingRay(u,w.direction()),(gamma+2));
213 ASSERT( gr == closestOnBoundedRayLinearWithPredicate(GridPointOnProbingRay(u,w.direction()),(gamma+2)) );
214 *out++ = gr.gridPoint();
217 } else { //a1 and a2 are both acute (or right),
218 //only y has yet to be considered (in addition to y1, y2)
219 //(because the angle between y1 and y2 is obtuse)
220 if (this->myPredicate(this->absolutePoint(y))) {
224 } //if a >= 0, we have an acute or right angle
225 //and no other point has to be considered.
226 //(if right angle, then case of cospherical points)
229 // ------------------------------------------------------------------------
230 template < typename TPredicate >
232 typename DGtal::PlaneProbingLNeighborhood<TPredicate>::GridPointOnProbingRay
233 DGtal::PlaneProbingLNeighborhood<TPredicate>::closestOnBoundedRayLogWithPredicate (GridPointOnProbingRay const& aRay, Integer const& aBound) const
235 GridPointOnProbingRay Xk = aRay, Xl = aRay.next(aRay.index()+aBound);
236 ASSERT(this->myPredicate(this->absolutePoint(Xk)));
239 Integer d = Xl.index() - Xk.index();
241 ASSERT(this->myPredicate(this->absolutePoint(Xk)));
243 GridPointOnProbingRay Xalpha = Xk.next(Integer(d / 4)),
244 Xbeta = Xk.next(Integer(d / 2)),
245 Xgamma = Xk.next(Integer(3*d/4));
247 ASSERT(Xk.index() < Xalpha.index() && Xalpha.index() < Xbeta.index() &&
248 Xbeta.index() < Xgamma.index() && Xgamma.index() < Xl.index());
250 if (this->myPredicate(this->absolutePoint(Xbeta)) &&
251 this->isSmallest(this->relativePoint(Xbeta), this->relativePoint(Xgamma))) {
253 } else if (! this->myPredicate(this->absolutePoint(Xalpha)) ||
254 this->isSmallest(this->relativePoint(Xbeta), this->relativePoint(Xalpha))) {
261 d = Xl.index() - Xk.index();
264 return closestOnBoundedRayLinearWithPredicate(Xk, d);
267 // ------------------------------------------------------------------------
268 template < typename TPredicate >
270 typename DGtal::PlaneProbingLNeighborhood<TPredicate>::GridPointOnProbingRay
271 DGtal::PlaneProbingLNeighborhood<TPredicate>::closestOnBoundedRayLinearWithPredicate (GridPointOnProbingRay const& aRay, const Integer& aBound) const
273 ASSERT(this->myPredicate(this->absolutePoint(aRay)));
276 GridPointOnProbingRay previousX = aRay, currentX = previousX.next(1);
277 while (this->myPredicate(this->absolutePoint(currentX)) &&
278 this->isSmallest(this->relativePoint(previousX), this->relativePoint(currentX)) &&
280 previousX = currentX;
281 currentX = previousX.next(1);
284 ASSERT(this->myPredicate(this->absolutePoint(previousX)));
289 // ------------------------------------------------------------------------
290 template < typename TPredicate >
292 typename DGtal::PlaneProbingLNeighborhood<TPredicate>::UpdateOperation
293 DGtal::PlaneProbingLNeighborhood<TPredicate>::
294 getOperationFromGridPoint (GridPoint const& aP) const
297 auto d = aP.direction();
298 return { { k, (k+1)%3, (k+2)%3 }, //permutation
299 { 1, -d.first, -d.second } //coefficients
303 // ------------------------------------------------------------------------
304 template < typename TPredicate >
307 DGtal::PlaneProbingLNeighborhood<TPredicate>::
308 updateGrid (const Index& aIdx)
310 //Let r1 and r2 be the two rays bound to the vertex of index 'aIdx'
311 PointOnProbingRay r1 = PointOnProbingRay({aIdx, (aIdx+1)%3, (aIdx+2)%3});
312 PointOnProbingRay r2 = PointOnProbingRay({aIdx, (aIdx+2)%3, (aIdx+1)%3});
313 //Check: do they are in the allowed rays?
314 if (this->isNeighbor(r1)) {
315 if (this->isNeighbor(r2)) {
317 myGrids[aIdx] = closestInGrid(aIdx);
320 myGrids[aIdx] = ClosestGridPoint( GridPoint(1, 0, aIdx), true, false );
323 if (this->isNeighbor(r2)) {
325 myGrids[aIdx] = ClosestGridPoint( GridPoint(0, 1, aIdx), false, true );
327 //if none of them, no candidate
328 myGrids[aIdx] = ClosestGridPoint( GridPoint(0, 0, aIdx), false, false );
333 // ------------------------------------------------------------------------
334 template < typename TPredicate >
336 typename DGtal::PlaneProbingLNeighborhood<TPredicate>::Point
337 DGtal::PlaneProbingLNeighborhood<TPredicate>::
338 direction (GridPoint const& aP) const
340 return aP.directionVector(this->myM);
343 ///////////////////////////////////////////////////////////////////////////////
344 // Interface - public :
347 * Writes/Displays the object on an output stream.
348 * @param out the output stream where the object is written.
350 template <typename TPredicate>
353 DGtal::PlaneProbingLNeighborhood<TPredicate>::selfDisplay ( std::ostream & out ) const
355 out << "[PlaneProbingLNeighborhood]";
359 * Checks the validity/consistency of the object.
360 * @return 'true' if the object is valid, 'false' otherwise.
362 template <typename TPredicate>
363 inline bool DGtal::PlaneProbingLNeighborhood<TPredicate>::isValid() const
370 ///////////////////////////////////////////////////////////////////////////////
371 // Implementation of inline functions //
373 template <typename TPredicate>
376 DGtal::operator<< ( std::ostream & out,
377 const DGtal::PlaneProbingLNeighborhood<TPredicate> & object )
379 object.selfDisplay( out );
384 ///////////////////////////////////////////////////////////////////////////////