exact_geodesic.cpp 78 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2018 Zhongshi Jiang <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "exact_geodesic.h"
  9. //Copyright (C) 2008 Danil Kirsanov, MIT License
  10. //Code from https://code.google.com/archive/p/geodesic/
  11. // Compiled into a single file by Zhongshi Jiang
  12. #include "PI.h"
  13. #include <algorithm>
  14. #include "IGL_ASSERT.h"
  15. #include <cmath>
  16. #include <cstddef>
  17. #include <ctime>
  18. #include <fstream>
  19. #include <iostream>
  20. #include <set>
  21. #include <vector>
  22. #include <memory>
  23. #include <cmath>
  24. namespace igl{
  25. namespace geodesic{
  26. //#include "geodesic_constants_and_simple_functions.h"
  27. //double const GEODESIC_INF = std::numeric_limits<double>::max();
  28. double const GEODESIC_INF = 1e100;
  29. //in order to avoid numerical problems with "infinitely small" intervals,
  30. //we drop all the intervals smaller than SMALLEST_INTERVAL_RATIO*edge_length
  31. double const SMALLEST_INTERVAL_RATIO = 1e-6;
  32. //double const SMALL_EPSILON = 1e-10;
  33. inline double cos_from_edges(double const a, //compute the cosine of the angle given the lengths of the edges
  34. double const b,
  35. double const c)
  36. {
  37. assert(a>1e-50);
  38. assert(b>1e-50);
  39. assert(c>1e-50);
  40. double result = (b*b + c*c - a*a)/(2.0*b*c);
  41. result = std::max(result, -1.0);
  42. return std::min(result, 1.0);
  43. }
  44. inline double angle_from_edges(double const a, //compute the cosine of the angle given the lengths of the edges
  45. double const b,
  46. double const c)
  47. {
  48. return acos(cos_from_edges(a,b,c));
  49. }
  50. template<class Points, class Faces>
  51. inline bool read_mesh_from_file(char* filename,
  52. Points& points,
  53. Faces& faces)
  54. {
  55. std::ifstream file(filename);
  56. assert(file.is_open());
  57. if(!file.is_open()) return false;
  58. unsigned num_points;
  59. file >> num_points;
  60. assert(num_points>=3);
  61. unsigned num_faces;
  62. file >> num_faces;
  63. points.resize(num_points*3);
  64. for(typename Points::iterator i=points.begin(); i!=points.end(); ++i)
  65. {
  66. file >> *i;
  67. }
  68. faces.resize(num_faces*3);
  69. for(typename Faces::iterator i=faces.begin(); i!=faces.end(); ++i)
  70. {
  71. file >> *i;
  72. }
  73. file.close();
  74. return true;
  75. }
  76. // #include "geodesic_memory"
  77. template<class T> //quickly allocates multiple elements of a given type; no deallocation
  78. class SimlpeMemoryAllocator
  79. {
  80. public:
  81. typedef T* pointer;
  82. SimlpeMemoryAllocator(unsigned block_size = 0,
  83. unsigned max_number_of_blocks = 0)
  84. {
  85. reset(block_size,
  86. max_number_of_blocks);
  87. };
  88. ~SimlpeMemoryAllocator(){};
  89. void reset(unsigned block_size,
  90. unsigned max_number_of_blocks)
  91. {
  92. m_block_size = block_size;
  93. m_max_number_of_blocks = max_number_of_blocks;
  94. m_current_position = 0;
  95. m_storage.reserve(max_number_of_blocks);
  96. m_storage.resize(1);
  97. m_storage[0].resize(block_size);
  98. };
  99. pointer allocate(unsigned const n) //allocate n units
  100. {
  101. assert(n < m_block_size);
  102. if(m_current_position + n >= m_block_size)
  103. {
  104. m_storage.push_back( std::vector<T>() );
  105. m_storage.back().resize(m_block_size);
  106. m_current_position = 0;
  107. }
  108. pointer result = & m_storage.back()[m_current_position];
  109. m_current_position += n;
  110. return result;
  111. };
  112. private:
  113. std::vector<std::vector<T> > m_storage;
  114. unsigned m_block_size; //size of a single block
  115. unsigned m_max_number_of_blocks; //maximum allowed number of blocks
  116. unsigned m_current_position; //first unused element inside the current block
  117. };
  118. template<class T> //quickly allocates and deallocates single elements of a given type
  119. class MemoryAllocator
  120. {
  121. public:
  122. typedef T* pointer;
  123. MemoryAllocator(unsigned block_size = 1024,
  124. unsigned max_number_of_blocks = 1024)
  125. {
  126. reset(block_size,
  127. max_number_of_blocks);
  128. };
  129. ~MemoryAllocator(){};
  130. void clear()
  131. {
  132. reset(m_block_size,
  133. m_max_number_of_blocks);
  134. }
  135. void reset(unsigned block_size,
  136. unsigned max_number_of_blocks)
  137. {
  138. m_block_size = block_size;
  139. m_max_number_of_blocks = max_number_of_blocks;
  140. assert(m_block_size > 0);
  141. assert(m_max_number_of_blocks > 0);
  142. m_current_position = 0;
  143. m_storage.reserve(max_number_of_blocks);
  144. m_storage.resize(1);
  145. m_storage[0].resize(block_size);
  146. m_deleted.clear();
  147. m_deleted.reserve(2*block_size);
  148. };
  149. pointer allocate() //allocates single unit of memory
  150. {
  151. pointer result;
  152. if(m_deleted.empty())
  153. {
  154. if(m_current_position + 1 >= m_block_size)
  155. {
  156. m_storage.push_back( std::vector<T>() );
  157. m_storage.back().resize(m_block_size);
  158. m_current_position = 0;
  159. }
  160. result = & m_storage.back()[m_current_position];
  161. ++m_current_position;
  162. }
  163. else
  164. {
  165. result = m_deleted.back();
  166. m_deleted.pop_back();
  167. }
  168. return result;
  169. };
  170. void deallocate(pointer p) //allocate n units
  171. {
  172. if(m_deleted.size() < m_deleted.capacity())
  173. {
  174. m_deleted.push_back(p);
  175. }
  176. };
  177. private:
  178. std::vector<std::vector<T> > m_storage;
  179. unsigned m_block_size; //size of a single block
  180. unsigned m_max_number_of_blocks; //maximum allowed number of blocks
  181. unsigned m_current_position; //first unused element inside the current block
  182. std::vector<pointer> m_deleted; //pointers to deleted elemets
  183. };
  184. class OutputBuffer
  185. {
  186. public:
  187. OutputBuffer():
  188. m_num_bytes(0)
  189. {}
  190. void clear()
  191. {
  192. m_num_bytes = 0;
  193. m_buffer = std::shared_ptr<double>();
  194. }
  195. template<class T>
  196. T* allocate(unsigned n)
  197. {
  198. double wanted = n*sizeof(T);
  199. if(wanted > m_num_bytes)
  200. {
  201. unsigned new_size = (unsigned) std::ceil(wanted / (double)sizeof(double));
  202. m_buffer = std::shared_ptr<double>(new double[new_size]);
  203. m_num_bytes = new_size*sizeof(double);
  204. }
  205. return (T*)m_buffer.get();
  206. }
  207. template <class T>
  208. T* get()
  209. {
  210. return (T*)m_buffer.get();
  211. }
  212. template<class T>
  213. unsigned capacity()
  214. {
  215. return (unsigned)std::floor((double)m_num_bytes/(double)sizeof(T));
  216. };
  217. private:
  218. std::shared_ptr<double> m_buffer;
  219. unsigned m_num_bytes;
  220. };
  221. class Vertex;
  222. class Edge;
  223. class Face;
  224. class Mesh;
  225. class MeshElementBase;
  226. typedef Vertex* vertex_pointer;
  227. typedef Edge* edge_pointer;
  228. typedef Face* face_pointer;
  229. typedef Mesh* mesh_pointer;
  230. typedef MeshElementBase* base_pointer;
  231. template <class Data> //simple vector that stores info about mesh references
  232. class SimpleVector //for efficiency, it uses an outside memory allocator
  233. {
  234. public:
  235. SimpleVector():
  236. m_size(0),
  237. m_begin(NULL)
  238. {};
  239. typedef Data* iterator;
  240. unsigned size(){return m_size;};
  241. iterator begin(){return m_begin;};
  242. iterator end(){return m_begin + m_size;};
  243. template<class DataPointer>
  244. void set_allocation(DataPointer begin, unsigned size)
  245. {
  246. assert(begin != NULL || size == 0);
  247. m_size = size;
  248. m_begin = (iterator)begin;
  249. }
  250. Data& operator[](unsigned i)
  251. {
  252. assert(i < m_size);
  253. return *(m_begin + i);
  254. }
  255. void clear()
  256. {
  257. m_size = 0;
  258. m_begin = NULL;
  259. }
  260. private:
  261. unsigned m_size;
  262. Data* m_begin;
  263. };
  264. enum PointType
  265. {
  266. VERTEX,
  267. EDGE,
  268. FACE,
  269. UNDEFINED_POINT
  270. };
  271. class MeshElementBase //prototype of vertices, edges and faces
  272. {
  273. public:
  274. typedef SimpleVector<vertex_pointer> vertex_pointer_vector;
  275. typedef SimpleVector<edge_pointer> edge_pointer_vector;
  276. typedef SimpleVector<face_pointer> face_pointer_vector;
  277. MeshElementBase():
  278. m_id(0),
  279. m_type(UNDEFINED_POINT)
  280. {};
  281. vertex_pointer_vector& adjacent_vertices(){return m_adjacent_vertices;};
  282. edge_pointer_vector& adjacent_edges(){return m_adjacent_edges;};
  283. face_pointer_vector& adjacent_faces(){return m_adjacent_faces;};
  284. unsigned& id(){return m_id;};
  285. PointType type(){return m_type;};
  286. protected:
  287. vertex_pointer_vector m_adjacent_vertices; //list of the adjacent vertices
  288. edge_pointer_vector m_adjacent_edges; //list of the adjacent edges
  289. face_pointer_vector m_adjacent_faces; //list of the adjacent faces
  290. unsigned m_id; //unique id
  291. PointType m_type; //vertex, edge or face
  292. };
  293. class Point3D //point in 3D and corresponding operations
  294. {
  295. public:
  296. Point3D(){};
  297. Point3D(Point3D* p)
  298. {
  299. x() = p->x();
  300. y() = p->y();
  301. z() = p->z();
  302. };
  303. double* xyz(){return m_coordinates;};
  304. double& x(){return *m_coordinates;};
  305. double& y(){return *(m_coordinates+1);};
  306. double& z(){return *(m_coordinates+2);};
  307. void set(double new_x, double new_y, double new_z)
  308. {
  309. x() = new_x;
  310. y() = new_y;
  311. z() = new_z;
  312. }
  313. void set(double* data)
  314. {
  315. x() = *data;
  316. y() = *(data+1);
  317. z() = *(data+2);
  318. }
  319. double distance(double* v)
  320. {
  321. double dx = m_coordinates[0] - v[0];
  322. double dy = m_coordinates[1] - v[1];
  323. double dz = m_coordinates[2] - v[2];
  324. return sqrt(dx*dx + dy*dy + dz*dz);
  325. };
  326. double distance(Point3D* v)
  327. {
  328. return distance(v->xyz());
  329. };
  330. void add(Point3D* v)
  331. {
  332. x() += v->x();
  333. y() += v->y();
  334. z() += v->z();
  335. };
  336. void multiply(double v)
  337. {
  338. x() *= v;
  339. y() *= v;
  340. z() *= v;
  341. };
  342. private:
  343. double m_coordinates[3]; //xyz
  344. };
  345. class Vertex: public MeshElementBase, public Point3D
  346. {
  347. public:
  348. Vertex()
  349. {
  350. m_type = VERTEX;
  351. };
  352. ~Vertex(){};
  353. bool& saddle_or_boundary(){return m_saddle_or_boundary;};
  354. private:
  355. //this flag speeds up exact geodesic algorithm
  356. bool m_saddle_or_boundary; //it is true if total adjacent angle is larger than 2*PI or this vertex belongs to the mesh boundary
  357. };
  358. class Face: public MeshElementBase
  359. {
  360. public:
  361. Face()
  362. {
  363. m_type = FACE;
  364. };
  365. ~Face(){};
  366. edge_pointer opposite_edge(vertex_pointer v);
  367. vertex_pointer opposite_vertex(edge_pointer e);
  368. edge_pointer next_edge(edge_pointer e, vertex_pointer v);
  369. double vertex_angle(vertex_pointer v)
  370. {
  371. for(unsigned i=0; i<3; ++i)
  372. {
  373. if(adjacent_vertices()[i]->id() == v->id())
  374. {
  375. return m_corner_angles[i];
  376. }
  377. }
  378. assert(0);
  379. return 0;
  380. }
  381. double* corner_angles(){return m_corner_angles;};
  382. private:
  383. double m_corner_angles[3]; //triangle angles in radians; angles correspond to vertices in m_adjacent_vertices
  384. };
  385. class Edge: public MeshElementBase
  386. {
  387. public:
  388. Edge()
  389. {
  390. m_type = EDGE;
  391. };
  392. ~Edge(){};
  393. double& length(){return m_length;};
  394. face_pointer opposite_face(face_pointer f)
  395. {
  396. if(adjacent_faces().size() == 1)
  397. {
  398. assert(adjacent_faces()[0]->id() == f->id());
  399. return NULL;
  400. }
  401. assert(adjacent_faces()[0]->id() == f->id() ||
  402. adjacent_faces()[1]->id() == f->id());
  403. return adjacent_faces()[0]->id() == f->id() ?
  404. adjacent_faces()[1] : adjacent_faces()[0];
  405. };
  406. vertex_pointer opposite_vertex(vertex_pointer v)
  407. {
  408. assert(belongs(v));
  409. return adjacent_vertices()[0]->id() == v->id() ?
  410. adjacent_vertices()[1] : adjacent_vertices()[0];
  411. };
  412. bool belongs(vertex_pointer v)
  413. {
  414. return adjacent_vertices()[0]->id() == v->id() ||
  415. adjacent_vertices()[1]->id() == v->id();
  416. }
  417. bool is_boundary(){return adjacent_faces().size() == 1;};
  418. vertex_pointer v0(){return adjacent_vertices()[0];};
  419. vertex_pointer v1(){return adjacent_vertices()[1];};
  420. void local_coordinates(Point3D* point,
  421. double& x,
  422. double& y)
  423. {
  424. double d0 = point->distance(v0());
  425. if(d0 < 1e-50)
  426. {
  427. x = 0.0;
  428. y = 0.0;
  429. return;
  430. }
  431. double d1 = point->distance(v1());
  432. if(d1 < 1e-50)
  433. {
  434. x = m_length;
  435. y = 0.0;
  436. return;
  437. }
  438. x = m_length/2.0 + (d0*d0 - d1*d1)/(2.0*m_length);
  439. y = sqrt(std::max(0.0, d0*d0 - x*x));
  440. return;
  441. }
  442. private:
  443. double m_length; //length of the edge
  444. };
  445. class SurfacePoint:public Point3D //point on the surface of the mesh
  446. {
  447. public:
  448. SurfacePoint():
  449. m_p(NULL)
  450. {};
  451. SurfacePoint(vertex_pointer v): //set the surface point in the vertex
  452. SurfacePoint::Point3D(v),
  453. m_p(v)
  454. {};
  455. SurfacePoint(face_pointer f): //set the surface point in the center of the face
  456. m_p(f)
  457. {
  458. set(0,0,0);
  459. add(f->adjacent_vertices()[0]);
  460. add(f->adjacent_vertices()[1]);
  461. add(f->adjacent_vertices()[2]);
  462. multiply(1./3.);
  463. };
  464. SurfacePoint(edge_pointer e, //set the surface point in the middle of the edge
  465. double a = 0.5):
  466. m_p(e)
  467. {
  468. double b = 1 - a;
  469. vertex_pointer v0 = e->adjacent_vertices()[0];
  470. vertex_pointer v1 = e->adjacent_vertices()[1];
  471. x() = b*v0->x() + a*v1->x();
  472. y() = b*v0->y() + a*v1->y();
  473. z() = b*v0->z() + a*v1->z();
  474. };
  475. SurfacePoint(base_pointer g,
  476. double x,
  477. double y,
  478. double z,
  479. PointType /*t = UNDEFINED_POINT*/):
  480. m_p(g)
  481. {
  482. set(x,y,z);
  483. };
  484. void initialize(SurfacePoint const& p)
  485. {
  486. *this = p;
  487. }
  488. ~SurfacePoint(){};
  489. PointType type(){return m_p ? m_p->type() : UNDEFINED_POINT;};
  490. base_pointer& base_element(){return m_p;};
  491. protected:
  492. base_pointer m_p; //could be face, vertex or edge pointer
  493. };
  494. inline edge_pointer Face::opposite_edge(vertex_pointer v)
  495. {
  496. for(unsigned i=0; i<3; ++i)
  497. {
  498. edge_pointer e = adjacent_edges()[i];
  499. if(!e->belongs(v))
  500. {
  501. return e;
  502. }
  503. }
  504. assert(0);
  505. return NULL;
  506. }
  507. inline vertex_pointer Face::opposite_vertex(edge_pointer e)
  508. {
  509. for(unsigned i=0; i<3; ++i)
  510. {
  511. vertex_pointer v = adjacent_vertices()[i];
  512. if(!e->belongs(v))
  513. {
  514. return v;
  515. }
  516. }
  517. assert(0);
  518. return NULL;
  519. }
  520. inline edge_pointer Face::next_edge(edge_pointer e, vertex_pointer v)
  521. {
  522. assert(e->belongs(v));
  523. for(unsigned i=0; i<3; ++i)
  524. {
  525. edge_pointer next = adjacent_edges()[i];
  526. if(e->id() != next->id() && next->belongs(v))
  527. {
  528. return next;
  529. }
  530. }
  531. assert(0);
  532. return NULL;
  533. }
  534. struct HalfEdge //prototype of the edge; used for mesh construction
  535. {
  536. unsigned face_id;
  537. unsigned vertex_0; //adjacent vertices sorted by id value
  538. unsigned vertex_1; //they are sorted, vertex_0 < vertex_1
  539. };
  540. inline bool operator < (const HalfEdge &x, const HalfEdge &y)
  541. {
  542. if(x.vertex_0 == y.vertex_0)
  543. {
  544. return x.vertex_1 < y.vertex_1;
  545. }
  546. else
  547. {
  548. return x.vertex_0 < y.vertex_0;
  549. }
  550. }
  551. inline bool operator != (const HalfEdge &x, const HalfEdge &y)
  552. {
  553. return x.vertex_0 != y.vertex_0 || x.vertex_1 != y.vertex_1;
  554. }
  555. inline bool operator == (const HalfEdge &x, const HalfEdge &y)
  556. {
  557. return x.vertex_0 == y.vertex_0 && x.vertex_1 == y.vertex_1;
  558. }
  559. struct edge_visible_from_source
  560. {
  561. unsigned source;
  562. edge_pointer edge;
  563. };
  564. class Mesh
  565. {
  566. public:
  567. Mesh()
  568. {};
  569. ~Mesh(){};
  570. template<class Points, class Faces>
  571. void initialize_mesh_data(unsigned num_vertices,
  572. Points& p,
  573. unsigned num_faces,
  574. Faces& tri); //build mesh from regular point-triangle representation
  575. template<class Points, class Faces>
  576. void initialize_mesh_data(Points& p, Faces& tri); //build mesh from regular point-triangle representation
  577. std::vector<Vertex>& vertices(){return m_vertices;};
  578. std::vector<Edge>& edges(){return m_edges;};
  579. std::vector<Face>& faces(){return m_faces;};
  580. unsigned closest_vertices(SurfacePoint* p,
  581. std::vector<vertex_pointer>* storage = NULL); //list vertices closest to the point
  582. private:
  583. void build_adjacencies(); //build internal structure of the mesh
  584. bool verify(); //verifies connectivity of the mesh and prints some debug info
  585. typedef void* void_pointer;
  586. void_pointer allocate_pointers(unsigned n)
  587. {
  588. return m_pointer_allocator.allocate(n);
  589. }
  590. std::vector<Vertex> m_vertices;
  591. std::vector<Edge> m_edges;
  592. std::vector<Face> m_faces;
  593. SimlpeMemoryAllocator<void_pointer> m_pointer_allocator; //fast memory allocating for Face/Vertex/Edge cross-references
  594. };
  595. inline unsigned Mesh::closest_vertices(SurfacePoint* p,
  596. std::vector<vertex_pointer>* storage)
  597. {
  598. assert(p->type() != UNDEFINED_POINT);
  599. if(p->type() == VERTEX)
  600. {
  601. if(storage)
  602. {
  603. storage->push_back(static_cast<vertex_pointer>(p->base_element()));
  604. }
  605. return 1;
  606. }
  607. else if(p->type() == FACE)
  608. {
  609. if(storage)
  610. {
  611. vertex_pointer* vp= p->base_element()->adjacent_vertices().begin();
  612. storage->push_back(*vp);
  613. storage->push_back(*(vp+1));
  614. storage->push_back(*(vp+2));
  615. }
  616. return 2;
  617. }
  618. else if(p->type() == EDGE) //for edge include all 4 adjacent vertices
  619. {
  620. edge_pointer edge = static_cast<edge_pointer>(p->base_element());
  621. if(storage)
  622. {
  623. storage->push_back(edge->adjacent_vertices()[0]);
  624. storage->push_back(edge->adjacent_vertices()[1]);
  625. for(unsigned i = 0; i < edge->adjacent_faces().size(); ++i)
  626. {
  627. face_pointer face = edge->adjacent_faces()[i];
  628. storage->push_back(face->opposite_vertex(edge));
  629. }
  630. }
  631. return 2 + edge->adjacent_faces().size();
  632. }
  633. assert(0);
  634. return 0;
  635. }
  636. template<class Points, class Faces>
  637. void Mesh::initialize_mesh_data(Points& p, Faces& tri) //build mesh from regular point-triangle representation
  638. {
  639. assert(p.size() % 3 == 0);
  640. unsigned const num_vertices = p.size() / 3;
  641. assert(tri.size() % 3 == 0);
  642. unsigned const num_faces = tri.size() / 3;
  643. initialize_mesh_data(num_vertices, p, num_faces, tri);
  644. }
  645. template<class Points, class Faces>
  646. void Mesh::initialize_mesh_data(unsigned num_vertices,
  647. Points& p,
  648. unsigned num_faces,
  649. Faces& tri)
  650. {
  651. unsigned const approximate_number_of_internal_pointers = (num_vertices + num_faces)*4;
  652. unsigned const max_number_of_pointer_blocks = 100;
  653. m_pointer_allocator.reset(approximate_number_of_internal_pointers,
  654. max_number_of_pointer_blocks);
  655. m_vertices.resize(num_vertices);
  656. for(unsigned i=0; i<num_vertices; ++i) //copy coordinates to vertices
  657. {
  658. Vertex& v = m_vertices[i];
  659. v.id() = i;
  660. unsigned shift = 3*i;
  661. v.x() = p[shift];
  662. v.y() = p[shift + 1];
  663. v.z() = p[shift + 2];
  664. }
  665. m_faces.resize(num_faces);
  666. for(unsigned i=0; i<num_faces; ++i) //copy adjacent vertices to polygons/faces
  667. {
  668. Face& f = m_faces[i];
  669. f.id() = i;
  670. f.adjacent_vertices().set_allocation(allocate_pointers(3),3); //allocate three units of memory
  671. unsigned shift = 3*i;
  672. for(unsigned j=0; j<3; ++j)
  673. {
  674. unsigned vertex_index = tri[shift + j];
  675. assert(vertex_index < num_vertices);
  676. f.adjacent_vertices()[j] = &m_vertices[vertex_index];
  677. }
  678. }
  679. build_adjacencies(); //build the structure of the mesh
  680. }
  681. inline void Mesh::build_adjacencies()
  682. {
  683. // Vertex->adjacent Faces
  684. std::vector<unsigned> count(m_vertices.size()); //count adjacent vertices
  685. for(unsigned i=0; i<m_faces.size(); ++i)
  686. {
  687. Face& f = m_faces[i];
  688. for(unsigned j=0; j<3; ++j)
  689. {
  690. unsigned vertex_id = f.adjacent_vertices()[j]->id();
  691. assert(vertex_id < m_vertices.size());
  692. count[vertex_id]++;
  693. }
  694. }
  695. for(unsigned i=0; i<m_vertices.size(); ++i) //reserve space
  696. {
  697. Vertex& v = m_vertices[i];
  698. unsigned num_adjacent_faces = count[i];
  699. v.adjacent_faces().set_allocation(allocate_pointers(num_adjacent_faces), //allocate three units of memory
  700. num_adjacent_faces);
  701. }
  702. std::fill(count.begin(), count.end(), 0);
  703. for(unsigned i=0; i<m_faces.size(); ++i)
  704. {
  705. Face& f = m_faces[i];
  706. for(unsigned j=0; j<3; ++j)
  707. {
  708. vertex_pointer v = f.adjacent_vertices()[j];
  709. v->adjacent_faces()[count[v->id()]++] = &f;
  710. }
  711. }
  712. //find all edges
  713. //i.e. find all half-edges, sort and combine them into edges
  714. std::vector<HalfEdge> half_edges(m_faces.size()*3);
  715. unsigned k = 0;
  716. for(unsigned i=0; i<m_faces.size(); ++i)
  717. {
  718. Face& f = m_faces[i];
  719. for(unsigned j=0; j<3; ++j)
  720. {
  721. half_edges[k].face_id = i;
  722. unsigned vertex_id_1 = f.adjacent_vertices()[j]->id();
  723. unsigned vertex_id_2 = f.adjacent_vertices()[(j+1) % 3]->id();
  724. half_edges[k].vertex_0 = std::min(vertex_id_1, vertex_id_2);
  725. half_edges[k].vertex_1 = std::max(vertex_id_1, vertex_id_2);
  726. k++;
  727. }
  728. }
  729. std::sort(half_edges.begin(), half_edges.end());
  730. unsigned number_of_edges = 1;
  731. for(unsigned i=1; i<half_edges.size(); ++i)
  732. {
  733. if(half_edges[i] != half_edges[i-1])
  734. {
  735. ++number_of_edges;
  736. }
  737. else
  738. {
  739. if(i<half_edges.size()-1) //sanity check: there should be at most two equal half-edges
  740. { //if it fails, most likely the input data are messed up
  741. assert(half_edges[i] != half_edges[i+1]);
  742. }
  743. }
  744. }
  745. // Edges->adjacent Vertices and Faces
  746. m_edges.resize(number_of_edges);
  747. unsigned edge_id = 0;
  748. for(unsigned i=0; i<half_edges.size();)
  749. {
  750. Edge& e = m_edges[edge_id];
  751. e.id() = edge_id++;
  752. e.adjacent_vertices().set_allocation(allocate_pointers(2),2); //allocate two units of memory
  753. e.adjacent_vertices()[0] = &m_vertices[half_edges[i].vertex_0];
  754. e.adjacent_vertices()[1] = &m_vertices[half_edges[i].vertex_1];
  755. e.length() = e.adjacent_vertices()[0]->distance(e.adjacent_vertices()[1]);
  756. assert(e.length() > 1e-100); //algorithm works well with non-degenerate meshes only
  757. if(i != half_edges.size()-1 && half_edges[i] == half_edges[i+1]) //double edge
  758. {
  759. e.adjacent_faces().set_allocation(allocate_pointers(2),2);
  760. e.adjacent_faces()[0] = &m_faces[half_edges[i].face_id];
  761. e.adjacent_faces()[1] = &m_faces[half_edges[i+1].face_id];
  762. i += 2;
  763. }
  764. else //single edge
  765. {
  766. e.adjacent_faces().set_allocation(allocate_pointers(1),1); //one adjucent faces
  767. e.adjacent_faces()[0] = &m_faces[half_edges[i].face_id];
  768. i += 1;
  769. }
  770. }
  771. // Vertices->adjacent Edges
  772. std::fill(count.begin(), count.end(), 0);
  773. for(unsigned i=0; i<m_edges.size(); ++i)
  774. {
  775. Edge& e = m_edges[i];
  776. assert(e.adjacent_vertices().size()==2);
  777. count[e.adjacent_vertices()[0]->id()]++;
  778. count[e.adjacent_vertices()[1]->id()]++;
  779. }
  780. for(unsigned i=0; i<m_vertices.size(); ++i)
  781. {
  782. m_vertices[i].adjacent_edges().set_allocation(allocate_pointers(count[i]),
  783. count[i]);
  784. }
  785. std::fill(count.begin(), count.end(), 0);
  786. for(unsigned i=0; i<m_edges.size(); ++i)
  787. {
  788. Edge& e = m_edges[i];
  789. for(unsigned j=0; j<2; ++j)
  790. {
  791. vertex_pointer v = e.adjacent_vertices()[j];
  792. v->adjacent_edges()[count[v->id()]++] = &e;
  793. }
  794. }
  795. // Faces->adjacent Edges
  796. for(unsigned i=0; i<m_faces.size(); ++i)
  797. {
  798. m_faces[i].adjacent_edges().set_allocation(allocate_pointers(3),3);
  799. }
  800. count.resize(m_faces.size());
  801. std::fill(count.begin(), count.end(), 0);
  802. for(unsigned i=0; i<m_edges.size(); ++i)
  803. {
  804. Edge& e = m_edges[i];
  805. for(unsigned j=0; j<e.adjacent_faces().size(); ++j)
  806. {
  807. face_pointer f = e.adjacent_faces()[j];
  808. assert(count[f->id()]<3);
  809. f->adjacent_edges()[count[f->id()]++] = &e;
  810. }
  811. }
  812. //compute angles for the faces
  813. for(unsigned i=0; i<m_faces.size(); ++i)
  814. {
  815. Face& f = m_faces[i];
  816. double abc[3];
  817. double sum = 0;
  818. for(unsigned j=0; j<3; ++j) //compute angle adjacent to the vertex j
  819. {
  820. for(unsigned k=0; k<3; ++k)
  821. {
  822. vertex_pointer v = f.adjacent_vertices()[(j + k)%3];
  823. abc[k] = f.opposite_edge(v)->length();
  824. }
  825. double angle = angle_from_edges(abc[0], abc[1], abc[2]);
  826. assert(angle>1e-5); //algorithm works well with non-degenerate meshes only
  827. f.corner_angles()[j] = angle;
  828. sum += angle;
  829. }
  830. IGL_ASSERT(std::abs(sum - igl::PI) < 1e-5); //algorithm works well with non-degenerate meshes only
  831. }
  832. //define m_turn_around_flag for vertices
  833. std::vector<double> total_vertex_angle(m_vertices.size());
  834. for(unsigned i=0; i<m_faces.size(); ++i)
  835. {
  836. Face& f = m_faces[i];
  837. for(unsigned j=0; j<3; ++j)
  838. {
  839. vertex_pointer v = f.adjacent_vertices()[j];
  840. total_vertex_angle[v->id()] += f.corner_angles()[j];
  841. }
  842. }
  843. for(unsigned i=0; i<m_vertices.size(); ++i)
  844. {
  845. Vertex& v = m_vertices[i];
  846. v.saddle_or_boundary() = (total_vertex_angle[v.id()] > 2.0*igl::PI - 1e-5);
  847. }
  848. for(unsigned i=0; i<m_edges.size(); ++i)
  849. {
  850. Edge& e = m_edges[i];
  851. if(e.is_boundary())
  852. {
  853. e.adjacent_vertices()[0]->saddle_or_boundary() = true;
  854. e.adjacent_vertices()[1]->saddle_or_boundary() = true;
  855. }
  856. }
  857. assert(verify());
  858. }
  859. inline bool Mesh::verify() //verifies connectivity of the mesh and prints some debug info
  860. {
  861. // make sure that all vertices are mentioned at least once.
  862. // though the loose vertex is not a bug, it most likely indicates that something is wrong with the mesh
  863. std::vector<bool> map(m_vertices.size(), false);
  864. for(unsigned i=0; i<m_edges.size(); ++i)
  865. {
  866. edge_pointer e = &m_edges[i];
  867. map[e->adjacent_vertices()[0]->id()] = true;
  868. map[e->adjacent_vertices()[1]->id()] = true;
  869. }
  870. assert(std::find(map.begin(), map.end(), false) == map.end());
  871. //make sure that the mesh is connected trough its edges
  872. //if mesh has more than one connected component, it is most likely a bug
  873. std::vector<face_pointer> stack(1,&m_faces[0]);
  874. stack.reserve(m_faces.size());
  875. map.resize(m_faces.size());
  876. std::fill(map.begin(), map.end(), false);
  877. map[0] = true;
  878. while(!stack.empty())
  879. {
  880. face_pointer f = stack.back();
  881. stack.pop_back();
  882. for(unsigned i=0; i<3; ++i)
  883. {
  884. edge_pointer e = f->adjacent_edges()[i];
  885. face_pointer f_adjacent = e->opposite_face(f);
  886. if(f_adjacent && !map[f_adjacent->id()])
  887. {
  888. map[f_adjacent->id()] = true;
  889. stack.push_back(f_adjacent);
  890. }
  891. }
  892. }
  893. assert(std::find(map.begin(), map.end(), false) == map.end());
  894. //print some mesh statistics that can be useful in debugging
  895. // std::cout << "mesh has " << m_vertices.size()
  896. // << " vertices, " << m_faces.size()
  897. // << " faces, " << m_edges.size()
  898. // << " edges\n";
  899. //unsigned total_boundary_edges = 0;
  900. double longest_edge = 0;
  901. double shortest_edge = 1e100;
  902. for(unsigned i=0; i<m_edges.size(); ++i)
  903. {
  904. Edge& e = m_edges[i];
  905. //total_boundary_edges += e.is_boundary() ? 1 : 0;
  906. longest_edge = std::max(longest_edge, e.length());
  907. shortest_edge = std::min(shortest_edge, e.length());
  908. }
  909. // std::cout << total_boundary_edges << " edges are boundary edges\n";
  910. // std::cout << "shortest/longest edges are "
  911. // << shortest_edge << "/"
  912. // << longest_edge << " = "
  913. // << shortest_edge/longest_edge
  914. // << std::endl;
  915. double minx = 1e100;
  916. double maxx = -1e100;
  917. double miny = 1e100;
  918. double maxy = -1e100;
  919. double minz = 1e100;
  920. double maxz = -1e100;
  921. for(unsigned i=0; i<m_vertices.size(); ++i)
  922. {
  923. Vertex& v = m_vertices[i];
  924. minx = std::min(minx, v.x());
  925. maxx = std::max(maxx, v.x());
  926. miny = std::min(miny, v.y());
  927. maxy = std::max(maxy, v.y());
  928. minz = std::min(minz, v.z());
  929. maxz = std::max(maxz, v.z());
  930. }
  931. // std::cout << "enclosing XYZ box:"
  932. // <<" X[" << minx << "," << maxx << "]"
  933. // <<" Y[" << miny << "," << maxy << "]"
  934. // <<" Z[" << minz << "," << maxz << "]"
  935. // << std::endl;
  936. //double dx = maxx - minx;
  937. //double dy = maxy - miny;
  938. //double dz = maxz - minz;
  939. // std::cout << "approximate diameter of the mesh is "
  940. // << sqrt(dx*dx + dy*dy + dz*dz)
  941. // << std::endl;
  942. double min_angle = 1e100;
  943. double max_angle = -1e100;
  944. for(unsigned i=0; i<m_faces.size(); ++i)
  945. {
  946. Face& f = m_faces[i];
  947. for(unsigned j=0; j<3; ++j)
  948. {
  949. double angle = f.corner_angles()[j];
  950. min_angle = std::min(min_angle, angle);
  951. max_angle = std::max(max_angle, angle);
  952. }
  953. }
  954. // std::cout << "min/max face angles are "
  955. // << min_angle/igl::PI*180.0 << "/"
  956. // << max_angle/igl::PI*180.0
  957. // << " degrees\n";
  958. // std::cout << std::endl;
  959. return true;
  960. }
  961. inline void fill_surface_point_structure(geodesic::SurfacePoint* point,
  962. double* data,
  963. Mesh* mesh)
  964. {
  965. point->set(data);
  966. unsigned type = (unsigned) data[3];
  967. unsigned id = (unsigned) data[4];
  968. if(type == 0) //vertex
  969. {
  970. point->base_element() = &mesh->vertices()[id];
  971. }
  972. else if(type == 1) //edge
  973. {
  974. point->base_element() = &mesh->edges()[id];
  975. }
  976. else //face
  977. {
  978. point->base_element() = &mesh->faces()[id];
  979. }
  980. }
  981. inline void fill_surface_point_double(geodesic::SurfacePoint* point,
  982. double* data,
  983. long /*mesh_id*/)
  984. {
  985. data[0] = point->x();
  986. data[1] = point->y();
  987. data[2] = point->z();
  988. data[4] = point->base_element()->id();
  989. if(point->type() == VERTEX) //vertex
  990. {
  991. data[3] = 0;
  992. }
  993. else if(point->type() == EDGE) //edge
  994. {
  995. data[3] = 1;
  996. }
  997. else //face
  998. {
  999. data[3] = 2;
  1000. }
  1001. }
  1002. class Interval;
  1003. class IntervalList;
  1004. typedef Interval* interval_pointer;
  1005. typedef IntervalList* list_pointer;
  1006. class Interval //interval of the edge
  1007. {
  1008. public:
  1009. Interval(){};
  1010. ~Interval(){};
  1011. enum DirectionType
  1012. {
  1013. FROM_FACE_0,
  1014. FROM_FACE_1,
  1015. FROM_SOURCE,
  1016. UNDEFINED_DIRECTION
  1017. };
  1018. double signal(double x) //geodesic distance function at point x
  1019. {
  1020. assert(x>=0.0 && x <= m_edge->length());
  1021. if(m_d == GEODESIC_INF)
  1022. {
  1023. return GEODESIC_INF;
  1024. }
  1025. else
  1026. {
  1027. double dx = x - m_pseudo_x;
  1028. if(m_pseudo_y == 0.0)
  1029. {
  1030. return m_d + std::abs(dx);
  1031. }
  1032. else
  1033. {
  1034. return m_d + sqrt(dx*dx + m_pseudo_y*m_pseudo_y);
  1035. }
  1036. }
  1037. }
  1038. double max_distance(double end)
  1039. {
  1040. if(m_d == GEODESIC_INF)
  1041. {
  1042. return GEODESIC_INF;
  1043. }
  1044. else
  1045. {
  1046. double a = std::abs(m_start - m_pseudo_x);
  1047. double b = std::abs(end - m_pseudo_x);
  1048. return a > b ? m_d + sqrt(a*a + m_pseudo_y*m_pseudo_y):
  1049. m_d + sqrt(b*b + m_pseudo_y*m_pseudo_y);
  1050. }
  1051. }
  1052. void compute_min_distance(double stop) //compute min, given c,d theta, start, end.
  1053. {
  1054. assert(stop > m_start);
  1055. if(m_d == GEODESIC_INF)
  1056. {
  1057. m_min = GEODESIC_INF;
  1058. }
  1059. else if(m_start > m_pseudo_x)
  1060. {
  1061. m_min = signal(m_start);
  1062. }
  1063. else if(stop < m_pseudo_x)
  1064. {
  1065. m_min = signal(stop);
  1066. }
  1067. else
  1068. {
  1069. assert(m_pseudo_y<=0);
  1070. m_min = m_d - m_pseudo_y;
  1071. }
  1072. }
  1073. //compare two intervals in the queue
  1074. bool operator()(interval_pointer const x, interval_pointer const y) const
  1075. {
  1076. if(x->min() != y->min())
  1077. {
  1078. return x->min() < y->min();
  1079. }
  1080. else if(x->start() != y->start())
  1081. {
  1082. return x->start() < y->start();
  1083. }
  1084. else
  1085. {
  1086. return x->edge()->id() < y->edge()->id();
  1087. }
  1088. }
  1089. double stop() //return the endpoint of the interval
  1090. {
  1091. return m_next ? m_next->start() : m_edge->length();
  1092. }
  1093. double hypotenuse(double a, double b)
  1094. {
  1095. return sqrt(a*a + b*b);
  1096. }
  1097. void find_closest_point(double const x,
  1098. double const y,
  1099. double& offset,
  1100. double& distance); //find the point on the interval that is closest to the point (alpha, s)
  1101. double& start(){return m_start;};
  1102. double& d(){return m_d;};
  1103. double& pseudo_x(){return m_pseudo_x;};
  1104. double& pseudo_y(){return m_pseudo_y;};
  1105. double& min(){return m_min;};
  1106. interval_pointer& next(){return m_next;};
  1107. edge_pointer& edge(){return m_edge;};
  1108. DirectionType& direction(){return m_direction;};
  1109. bool visible_from_source(){return m_direction == FROM_SOURCE;};
  1110. unsigned& source_index(){return m_source_index;};
  1111. void initialize(edge_pointer edge,
  1112. SurfacePoint* point = NULL,
  1113. unsigned source_index = 0);
  1114. protected:
  1115. double m_start; //initial point of the interval on the edge
  1116. double m_d; //distance from the source to the pseudo-source
  1117. double m_pseudo_x; //coordinates of the pseudo-source in the local coordinate system
  1118. double m_pseudo_y; //y-coordinate should be always negative
  1119. double m_min; //minimum distance on the interval
  1120. interval_pointer m_next; //pointer to the next interval in the list
  1121. edge_pointer m_edge; //edge that the interval belongs to
  1122. unsigned m_source_index; //the source it belongs to
  1123. DirectionType m_direction; //where the interval is coming from
  1124. };
  1125. struct IntervalWithStop : public Interval
  1126. {
  1127. public:
  1128. double& stop(){return m_stop;};
  1129. protected:
  1130. double m_stop;
  1131. };
  1132. class IntervalList //list of the of intervals of the given edge
  1133. {
  1134. public:
  1135. IntervalList(){m_first = NULL;};
  1136. ~IntervalList(){};
  1137. void clear()
  1138. {
  1139. m_first = NULL;
  1140. };
  1141. void initialize(edge_pointer e)
  1142. {
  1143. m_edge = e;
  1144. m_first = NULL;
  1145. };
  1146. interval_pointer covering_interval(double offset) //returns the interval that covers the offset
  1147. {
  1148. assert(offset >= 0.0 && offset <= m_edge->length());
  1149. interval_pointer p = m_first;
  1150. while(p && p->stop() < offset)
  1151. {
  1152. p = p->next();
  1153. }
  1154. return p;// && p->start() <= offset ? p : NULL;
  1155. };
  1156. void find_closest_point(SurfacePoint* point,
  1157. double& offset,
  1158. double& distance,
  1159. interval_pointer& interval)
  1160. {
  1161. interval_pointer p = m_first;
  1162. distance = GEODESIC_INF;
  1163. interval = NULL;
  1164. double x,y;
  1165. m_edge->local_coordinates(point, x, y);
  1166. while(p)
  1167. {
  1168. if(p->min()<GEODESIC_INF)
  1169. {
  1170. double o, d;
  1171. p->find_closest_point(x, y, o, d);
  1172. if(d < distance)
  1173. {
  1174. distance = d;
  1175. offset = o;
  1176. interval = p;
  1177. }
  1178. }
  1179. p = p->next();
  1180. }
  1181. };
  1182. unsigned number_of_intervals()
  1183. {
  1184. interval_pointer p = m_first;
  1185. unsigned count = 0;
  1186. while(p)
  1187. {
  1188. ++count;
  1189. p = p->next();
  1190. }
  1191. return count;
  1192. }
  1193. interval_pointer last()
  1194. {
  1195. interval_pointer p = m_first;
  1196. if(p)
  1197. {
  1198. while(p->next())
  1199. {
  1200. p = p->next();
  1201. }
  1202. }
  1203. return p;
  1204. }
  1205. double signal(double x)
  1206. {
  1207. interval_pointer interval = covering_interval(x);
  1208. return interval ? interval->signal(x) : GEODESIC_INF;
  1209. }
  1210. interval_pointer& first(){return m_first;};
  1211. edge_pointer& edge(){return m_edge;};
  1212. private:
  1213. interval_pointer m_first; //pointer to the first member of the list
  1214. edge_pointer m_edge; //edge that owns this list
  1215. };
  1216. class SurfacePointWithIndex : public SurfacePoint
  1217. {
  1218. public:
  1219. unsigned index(){return m_index;};
  1220. void initialize(SurfacePoint& p, unsigned index)
  1221. {
  1222. SurfacePoint::initialize(p);
  1223. m_index = index;
  1224. }
  1225. bool operator()(SurfacePointWithIndex* x, SurfacePointWithIndex* y) const //used for sorting
  1226. {
  1227. assert(x->type() != UNDEFINED_POINT && y->type() !=UNDEFINED_POINT);
  1228. if(x->type() != y->type())
  1229. {
  1230. return x->type() < y->type();
  1231. }
  1232. else
  1233. {
  1234. return x->base_element()->id() < y->base_element()->id();
  1235. }
  1236. }
  1237. private:
  1238. unsigned m_index;
  1239. };
  1240. class SortedSources : public std::vector<SurfacePointWithIndex>
  1241. {
  1242. private:
  1243. typedef std::vector<SurfacePointWithIndex*> sorted_vector_type;
  1244. public:
  1245. typedef sorted_vector_type::iterator sorted_iterator;
  1246. typedef std::pair<sorted_iterator, sorted_iterator> sorted_iterator_pair;
  1247. sorted_iterator_pair sources(base_pointer mesh_element)
  1248. {
  1249. m_search_dummy.base_element() = mesh_element;
  1250. return equal_range(m_sorted.begin(),
  1251. m_sorted.end(),
  1252. &m_search_dummy,
  1253. m_compare_less);
  1254. }
  1255. void initialize(std::vector<SurfacePoint>& sources) //we initialize the sources by copie
  1256. {
  1257. resize(sources.size());
  1258. m_sorted.resize(sources.size());
  1259. for(unsigned i=0; i<sources.size(); ++i)
  1260. {
  1261. SurfacePointWithIndex& p = *(begin() + i);
  1262. p.initialize(sources[i],i);
  1263. m_sorted[i] = &p;
  1264. }
  1265. std::sort(m_sorted.begin(), m_sorted.end(), m_compare_less);
  1266. };
  1267. SurfacePointWithIndex& operator[](unsigned i)
  1268. {
  1269. assert(i < size());
  1270. return *(begin() + i);
  1271. }
  1272. private:
  1273. sorted_vector_type m_sorted;
  1274. SurfacePointWithIndex m_search_dummy; //used as a search template
  1275. SurfacePointWithIndex m_compare_less; //used as a compare functor
  1276. };
  1277. inline void Interval::find_closest_point(double const rs,
  1278. double const hs,
  1279. double& r,
  1280. double& d_out) //find the point on the interval that is closest to the point (alpha, s)
  1281. {
  1282. if(m_d == GEODESIC_INF)
  1283. {
  1284. r = GEODESIC_INF;
  1285. d_out = GEODESIC_INF;
  1286. return;
  1287. }
  1288. double hc = -m_pseudo_y;
  1289. double rc = m_pseudo_x;
  1290. double end = stop();
  1291. double local_epsilon = SMALLEST_INTERVAL_RATIO*m_edge->length();
  1292. if(std::abs(hs+hc) < local_epsilon)
  1293. {
  1294. if(rs<=m_start)
  1295. {
  1296. r = m_start;
  1297. d_out = signal(m_start) + std::abs(rs - m_start);
  1298. }
  1299. else if(rs>=end)
  1300. {
  1301. r = end;
  1302. d_out = signal(end) + fabs(end - rs);
  1303. }
  1304. else
  1305. {
  1306. r = rs;
  1307. d_out = signal(rs);
  1308. }
  1309. }
  1310. else
  1311. {
  1312. double ri = (rs*hc + hs*rc)/(hs+hc);
  1313. if(ri<m_start)
  1314. {
  1315. r = m_start;
  1316. d_out = signal(m_start) + hypotenuse(m_start - rs, hs);
  1317. }
  1318. else if(ri>end)
  1319. {
  1320. r = end;
  1321. d_out = signal(end) + hypotenuse(end - rs, hs);
  1322. }
  1323. else
  1324. {
  1325. r = ri;
  1326. d_out = m_d + hypotenuse(rc - rs, hc + hs);
  1327. }
  1328. }
  1329. }
  1330. inline void Interval::initialize(edge_pointer edge,
  1331. SurfacePoint* source,
  1332. unsigned source_index)
  1333. {
  1334. m_next = NULL;
  1335. //m_geodesic_previous = NULL;
  1336. m_direction = UNDEFINED_DIRECTION;
  1337. m_edge = edge;
  1338. m_source_index = source_index;
  1339. m_start = 0.0;
  1340. //m_stop = edge->length();
  1341. if(!source)
  1342. {
  1343. m_d = GEODESIC_INF;
  1344. m_min = GEODESIC_INF;
  1345. return;
  1346. }
  1347. m_d = 0;
  1348. if(source->base_element()->type() == VERTEX)
  1349. {
  1350. if(source->base_element()->id() == edge->v0()->id())
  1351. {
  1352. m_pseudo_x = 0.0;
  1353. m_pseudo_y = 0.0;
  1354. m_min = 0.0;
  1355. return;
  1356. }
  1357. else if(source->base_element()->id() == edge->v1()->id())
  1358. {
  1359. m_pseudo_x = stop();
  1360. m_pseudo_y = 0.0;
  1361. m_min = 0.0;
  1362. return;
  1363. }
  1364. }
  1365. edge->local_coordinates(source, m_pseudo_x, m_pseudo_y);
  1366. m_pseudo_y = -m_pseudo_y;
  1367. compute_min_distance(stop());
  1368. }
  1369. // #include "geodesic_algorithm_base.h"
  1370. class GeodesicAlgorithmBase
  1371. {
  1372. public:
  1373. enum AlgorithmType
  1374. {
  1375. EXACT,
  1376. DIJKSTRA,
  1377. SUBDIVISION,
  1378. UNDEFINED_ALGORITHM
  1379. };
  1380. GeodesicAlgorithmBase(geodesic::Mesh* mesh):
  1381. m_type(UNDEFINED_ALGORITHM),
  1382. m_max_propagation_distance(1e100),
  1383. m_mesh(mesh)
  1384. {};
  1385. virtual ~GeodesicAlgorithmBase(){};
  1386. virtual void propagate(std::vector<SurfacePoint>& sources,
  1387. double max_propagation_distance = GEODESIC_INF, //propagation algorithm stops after reaching the certain distance from the source
  1388. std::vector<SurfacePoint>* stop_points = NULL) = 0; //or after ensuring that all the stop_points are covered
  1389. virtual void trace_back(SurfacePoint& destination, //trace back piecewise-linear path
  1390. std::vector<SurfacePoint>& path) = 0;
  1391. void geodesic(SurfacePoint& source,
  1392. SurfacePoint& destination,
  1393. std::vector<SurfacePoint>& path); //lazy people can find geodesic path with one function call
  1394. void geodesic(std::vector<SurfacePoint>& sources,
  1395. std::vector<SurfacePoint>& destinations,
  1396. std::vector<std::vector<SurfacePoint> >& paths); //lazy people can find geodesic paths with one function call
  1397. virtual unsigned best_source(SurfacePoint& point, //after propagation step is done, quickly find what source this point belongs to and what is the distance to this source
  1398. double& best_source_distance) = 0;
  1399. virtual void print_statistics() //print info about timing and memory usage in the propagation step of the algorithm
  1400. {
  1401. std::cout << "propagation step took " << m_time_consumed << " seconds " << std::endl;
  1402. };
  1403. AlgorithmType type(){return m_type;};
  1404. virtual std::string name();
  1405. geodesic::Mesh* mesh(){return m_mesh;};
  1406. protected:
  1407. void set_stop_conditions(std::vector<SurfacePoint>* stop_points,
  1408. double stop_distance);
  1409. double stop_distance()
  1410. {
  1411. return m_max_propagation_distance;
  1412. }
  1413. AlgorithmType m_type; // type of the algorithm
  1414. typedef std::pair<vertex_pointer, double> stop_vertex_with_distace_type;
  1415. std::vector<stop_vertex_with_distace_type> m_stop_vertices; // algorithm stops propagation after covering certain vertices
  1416. double m_max_propagation_distance; // or reaching the certain distance
  1417. geodesic::Mesh* m_mesh;
  1418. double m_time_consumed; //how much time does the propagation step takes
  1419. double m_propagation_distance_stopped; //at what distance (if any) the propagation algorithm stopped
  1420. };
  1421. inline double length(std::vector<SurfacePoint>& path)
  1422. {
  1423. double length = 0;
  1424. if(!path.empty())
  1425. {
  1426. for(unsigned i=0; i<path.size()-1; ++i)
  1427. {
  1428. length += path[i].distance(&path[i+1]);
  1429. }
  1430. }
  1431. return length;
  1432. }
  1433. inline void print_info_about_path(std::vector<SurfacePoint>& path)
  1434. {
  1435. std::cout << "number of the points in the path = " << path.size()
  1436. << ", length of the path = " << length(path)
  1437. << std::endl;
  1438. }
  1439. inline std::string GeodesicAlgorithmBase::name()
  1440. {
  1441. switch(m_type)
  1442. {
  1443. case EXACT:
  1444. return "exact";
  1445. case DIJKSTRA:
  1446. return "dijkstra";
  1447. case SUBDIVISION:
  1448. return "subdivision";
  1449. default:
  1450. case UNDEFINED_ALGORITHM:
  1451. return "undefined";
  1452. }
  1453. }
  1454. inline void GeodesicAlgorithmBase::geodesic(SurfacePoint& source,
  1455. SurfacePoint& destination,
  1456. std::vector<SurfacePoint>& path) //lazy people can find geodesic path with one function call
  1457. {
  1458. std::vector<SurfacePoint> sources(1, source);
  1459. std::vector<SurfacePoint> stop_points(1, destination);
  1460. double const max_propagation_distance = GEODESIC_INF;
  1461. propagate(sources,
  1462. max_propagation_distance,
  1463. &stop_points);
  1464. trace_back(destination, path);
  1465. }
  1466. inline void GeodesicAlgorithmBase::geodesic(std::vector<SurfacePoint>& sources,
  1467. std::vector<SurfacePoint>& destinations,
  1468. std::vector<std::vector<SurfacePoint> >& paths) //lazy people can find geodesic paths with one function call
  1469. {
  1470. double const max_propagation_distance = GEODESIC_INF;
  1471. propagate(sources,
  1472. max_propagation_distance,
  1473. &destinations); //we use desinations as stop points
  1474. paths.resize(destinations.size());
  1475. for(unsigned i=0; i<paths.size(); ++i)
  1476. {
  1477. trace_back(destinations[i], paths[i]);
  1478. }
  1479. }
  1480. inline void GeodesicAlgorithmBase::set_stop_conditions(std::vector<SurfacePoint>* stop_points,
  1481. double stop_distance)
  1482. {
  1483. m_max_propagation_distance = stop_distance;
  1484. if(!stop_points)
  1485. {
  1486. m_stop_vertices.clear();
  1487. return;
  1488. }
  1489. m_stop_vertices.resize(stop_points->size());
  1490. std::vector<vertex_pointer> possible_vertices;
  1491. for(unsigned i = 0; i < stop_points->size(); ++i)
  1492. {
  1493. SurfacePoint* point = &(*stop_points)[i];
  1494. possible_vertices.clear();
  1495. m_mesh->closest_vertices(point, &possible_vertices);
  1496. vertex_pointer closest_vertex = NULL;
  1497. double min_distance = 1e100;
  1498. for(unsigned j = 0; j < possible_vertices.size(); ++j)
  1499. {
  1500. double distance = point->distance(possible_vertices[j]);
  1501. if(distance < min_distance)
  1502. {
  1503. min_distance = distance;
  1504. closest_vertex = possible_vertices[j];
  1505. }
  1506. }
  1507. assert(closest_vertex);
  1508. m_stop_vertices[i].first = closest_vertex;
  1509. m_stop_vertices[i].second = min_distance;
  1510. }
  1511. }
  1512. class GeodesicAlgorithmExact : public GeodesicAlgorithmBase
  1513. {
  1514. public:
  1515. GeodesicAlgorithmExact(geodesic::Mesh* mesh):
  1516. GeodesicAlgorithmBase(mesh),
  1517. m_memory_allocator(mesh->edges().size(), mesh->edges().size()),
  1518. m_edge_interval_lists(mesh->edges().size())
  1519. {
  1520. m_type = EXACT;
  1521. for(unsigned i=0; i<m_edge_interval_lists.size(); ++i)
  1522. {
  1523. m_edge_interval_lists[i].initialize(&mesh->edges()[i]);
  1524. }
  1525. };
  1526. ~GeodesicAlgorithmExact(){};
  1527. void propagate(std::vector<SurfacePoint>& sources,
  1528. double max_propagation_distance = GEODESIC_INF, //propagation algorithm stops after reaching the certain distance from the source
  1529. std::vector<SurfacePoint>* stop_points = NULL); //or after ensuring that all the stop_points are covered
  1530. void trace_back(SurfacePoint& destination, //trace back piecewise-linear path
  1531. std::vector<SurfacePoint>& path);
  1532. unsigned best_source(SurfacePoint& point, //quickly find what source this point belongs to and what is the distance to this source
  1533. double& best_source_distance);
  1534. void print_statistics();
  1535. private:
  1536. typedef std::set<interval_pointer, Interval> IntervalQueue;
  1537. void update_list_and_queue(list_pointer list,
  1538. IntervalWithStop* candidates, //up to two candidates
  1539. unsigned num_candidates);
  1540. unsigned compute_propagated_parameters(double pseudo_x,
  1541. double pseudo_y,
  1542. double d, //parameters of the interval
  1543. double start,
  1544. double end, //start/end of the interval
  1545. double alpha, //corner angle
  1546. double L, //length of the new edge
  1547. bool first_interval, //if it is the first interval on the edge
  1548. bool last_interval,
  1549. bool turn_left,
  1550. bool turn_right,
  1551. IntervalWithStop* candidates); //if it is the last interval on the edge
  1552. void construct_propagated_intervals(bool invert,
  1553. edge_pointer edge,
  1554. face_pointer face, //constructs iNew from the rest of the data
  1555. IntervalWithStop* candidates,
  1556. unsigned& num_candidates,
  1557. interval_pointer source_interval);
  1558. double compute_positive_intersection(double start,
  1559. double pseudo_x,
  1560. double pseudo_y,
  1561. double sin_alpha,
  1562. double cos_alpha); //used in construct_propagated_intervals
  1563. unsigned intersect_intervals(interval_pointer zero,
  1564. IntervalWithStop* one); //intersecting two intervals with up to three intervals in the end
  1565. interval_pointer best_first_interval(SurfacePoint& point,
  1566. double& best_total_distance,
  1567. double& best_interval_position,
  1568. unsigned& best_source_index);
  1569. bool check_stop_conditions(unsigned& index);
  1570. void clear()
  1571. {
  1572. m_memory_allocator.clear();
  1573. m_queue.clear();
  1574. for(unsigned i=0; i<m_edge_interval_lists.size(); ++i)
  1575. {
  1576. m_edge_interval_lists[i].clear();
  1577. }
  1578. m_propagation_distance_stopped = GEODESIC_INF;
  1579. };
  1580. list_pointer interval_list(edge_pointer e)
  1581. {
  1582. return &m_edge_interval_lists[e->id()];
  1583. };
  1584. void set_sources(std::vector<SurfacePoint>& sources)
  1585. {
  1586. m_sources.initialize(sources);
  1587. }
  1588. void initialize_propagation_data();
  1589. void list_edges_visible_from_source(MeshElementBase* p,
  1590. std::vector<edge_pointer>& storage); //used in initialization
  1591. long visible_from_source(SurfacePoint& point); //used in backtracing
  1592. void best_point_on_the_edge_set(SurfacePoint& point,
  1593. std::vector<edge_pointer> const& storage,
  1594. interval_pointer& best_interval,
  1595. double& best_total_distance,
  1596. double& best_interval_position);
  1597. void possible_traceback_edges(SurfacePoint& point,
  1598. std::vector<edge_pointer>& storage);
  1599. bool erase_from_queue(interval_pointer p);
  1600. IntervalQueue m_queue; //interval queue
  1601. MemoryAllocator<Interval> m_memory_allocator; //quickly allocate and deallocate intervals
  1602. std::vector<IntervalList> m_edge_interval_lists; //every edge has its interval data
  1603. enum MapType {OLD, NEW}; //used for interval intersection
  1604. MapType map[5];
  1605. double start[6];
  1606. interval_pointer i_new[5];
  1607. unsigned m_queue_max_size; //used for statistics
  1608. unsigned m_iterations; //used for statistics
  1609. SortedSources m_sources;
  1610. };
  1611. inline void GeodesicAlgorithmExact::best_point_on_the_edge_set(SurfacePoint& point,
  1612. std::vector<edge_pointer> const& storage,
  1613. interval_pointer& best_interval,
  1614. double& best_total_distance,
  1615. double& best_interval_position)
  1616. {
  1617. best_total_distance = 1e100;
  1618. for(unsigned i=0; i<storage.size(); ++i)
  1619. {
  1620. edge_pointer e = storage[i];
  1621. list_pointer list = interval_list(e);
  1622. double offset;
  1623. double distance;
  1624. interval_pointer interval;
  1625. list->find_closest_point(&point,
  1626. offset,
  1627. distance,
  1628. interval);
  1629. if(distance < best_total_distance)
  1630. {
  1631. best_interval = interval;
  1632. best_total_distance = distance;
  1633. best_interval_position = offset;
  1634. }
  1635. }
  1636. }
  1637. inline void GeodesicAlgorithmExact::possible_traceback_edges(SurfacePoint& point,
  1638. std::vector<edge_pointer>& storage)
  1639. {
  1640. storage.clear();
  1641. if(point.type() == VERTEX)
  1642. {
  1643. vertex_pointer v = static_cast<vertex_pointer>(point.base_element());
  1644. for(unsigned i=0; i<v->adjacent_faces().size(); ++i)
  1645. {
  1646. face_pointer f = v->adjacent_faces()[i];
  1647. storage.push_back(f->opposite_edge(v));
  1648. }
  1649. }
  1650. else if(point.type() == EDGE)
  1651. {
  1652. edge_pointer e = static_cast<edge_pointer>(point.base_element());
  1653. for(unsigned i=0; i<e->adjacent_faces().size(); ++i)
  1654. {
  1655. face_pointer f = e->adjacent_faces()[i];
  1656. storage.push_back(f->next_edge(e,e->v0()));
  1657. storage.push_back(f->next_edge(e,e->v1()));
  1658. }
  1659. }
  1660. else
  1661. {
  1662. face_pointer f = static_cast<face_pointer>(point.base_element());
  1663. storage.push_back(f->adjacent_edges()[0]);
  1664. storage.push_back(f->adjacent_edges()[1]);
  1665. storage.push_back(f->adjacent_edges()[2]);
  1666. }
  1667. }
  1668. inline long GeodesicAlgorithmExact::visible_from_source(SurfacePoint& point) //negative if not visible
  1669. {
  1670. assert(point.type() != UNDEFINED_POINT);
  1671. if(point.type() == EDGE)
  1672. {
  1673. edge_pointer e = static_cast<edge_pointer>(point.base_element());
  1674. list_pointer list = interval_list(e);
  1675. double position = std::min(point.distance(e->v0()), e->length());
  1676. interval_pointer interval = list->covering_interval(position);
  1677. //assert(interval);
  1678. if(interval && interval->visible_from_source())
  1679. {
  1680. return (long)interval->source_index();
  1681. }
  1682. else
  1683. {
  1684. return -1;
  1685. }
  1686. }
  1687. else if(point.type() == FACE)
  1688. {
  1689. return -1;
  1690. }
  1691. else if(point.type() == VERTEX)
  1692. {
  1693. vertex_pointer v = static_cast<vertex_pointer>(point.base_element());
  1694. for(unsigned i=0; i<v->adjacent_edges().size(); ++i)
  1695. {
  1696. edge_pointer e = v->adjacent_edges()[i];
  1697. list_pointer list = interval_list(e);
  1698. double position = e->v0()->id() == v->id() ? 0.0 : e->length();
  1699. interval_pointer interval = list->covering_interval(position);
  1700. if(interval && interval->visible_from_source())
  1701. {
  1702. return (long)interval->source_index();
  1703. }
  1704. }
  1705. return -1;
  1706. }
  1707. assert(0);
  1708. return 0;
  1709. }
  1710. inline double GeodesicAlgorithmExact::compute_positive_intersection(double start,
  1711. double pseudo_x,
  1712. double pseudo_y,
  1713. double sin_alpha,
  1714. double cos_alpha)
  1715. {
  1716. assert(pseudo_y < 0);
  1717. double denominator = sin_alpha*(pseudo_x - start) - cos_alpha*pseudo_y;
  1718. if(denominator<0.0)
  1719. {
  1720. return -1.0;
  1721. }
  1722. double numerator = -pseudo_y*start;
  1723. if(numerator < 1e-30)
  1724. {
  1725. return 0.0;
  1726. }
  1727. if(denominator < 1e-30)
  1728. {
  1729. return -1.0;
  1730. }
  1731. return numerator/denominator;
  1732. }
  1733. inline void GeodesicAlgorithmExact::list_edges_visible_from_source(MeshElementBase* p,
  1734. std::vector<edge_pointer>& storage)
  1735. {
  1736. assert(p->type() != UNDEFINED_POINT);
  1737. if(p->type() == FACE)
  1738. {
  1739. face_pointer f = static_cast<face_pointer>(p);
  1740. for(unsigned i=0; i<3; ++i)
  1741. {
  1742. storage.push_back(f->adjacent_edges()[i]);
  1743. }
  1744. }
  1745. else if(p->type() == EDGE)
  1746. {
  1747. edge_pointer e = static_cast<edge_pointer>(p);
  1748. storage.push_back(e);
  1749. }
  1750. else //VERTEX
  1751. {
  1752. vertex_pointer v = static_cast<vertex_pointer>(p);
  1753. for(unsigned i=0; i<v->adjacent_edges().size(); ++i)
  1754. {
  1755. storage.push_back(v->adjacent_edges()[i]);
  1756. }
  1757. }
  1758. }
  1759. inline bool GeodesicAlgorithmExact::erase_from_queue(interval_pointer p)
  1760. {
  1761. if(p->min() < GEODESIC_INF/10.0)// && p->min >= queue->begin()->first)
  1762. {
  1763. assert(m_queue.count(p)<=1); //the set is unique
  1764. IntervalQueue::iterator it = m_queue.find(p);
  1765. if(it != m_queue.end())
  1766. {
  1767. m_queue.erase(it);
  1768. return true;
  1769. }
  1770. }
  1771. return false;
  1772. }
  1773. inline unsigned GeodesicAlgorithmExact::intersect_intervals(interval_pointer zero,
  1774. IntervalWithStop* one) //intersecting two intervals with up to three intervals in the end
  1775. {
  1776. assert(zero->edge()->id() == one->edge()->id());
  1777. assert(zero->stop() > one->start() && zero->start() < one->stop());
  1778. assert(one->min() < GEODESIC_INF/10.0);
  1779. double const local_epsilon = SMALLEST_INTERVAL_RATIO*one->edge()->length();
  1780. unsigned N=0;
  1781. if(zero->min() > GEODESIC_INF/10.0)
  1782. {
  1783. start[0] = zero->start();
  1784. if(zero->start() < one->start() - local_epsilon)
  1785. {
  1786. map[0] = OLD;
  1787. start[1] = one->start();
  1788. map[1] = NEW;
  1789. N = 2;
  1790. }
  1791. else
  1792. {
  1793. map[0] = NEW;
  1794. N = 1;
  1795. }
  1796. if(zero->stop() > one->stop() + local_epsilon)
  1797. {
  1798. map[N] = OLD; //"zero" interval
  1799. start[N++] = one->stop();
  1800. }
  1801. start[N+1] = zero->stop();
  1802. return N;
  1803. }
  1804. double const local_small_epsilon = 1e-8*one->edge()->length();
  1805. double D = zero->d() - one->d();
  1806. double x0 = zero->pseudo_x();
  1807. double x1 = one->pseudo_x();
  1808. double R0 = x0*x0 + zero->pseudo_y()*zero->pseudo_y();
  1809. double R1 = x1*x1 + one->pseudo_y()*one->pseudo_y();
  1810. double inter[2]; //points of intersection
  1811. char Ninter=0; //number of the points of the intersection
  1812. if(std::abs(D)<local_epsilon) //if d1 == d0, equation is linear
  1813. {
  1814. double denom = x1 - x0;
  1815. if(std::abs(denom)>local_small_epsilon)
  1816. {
  1817. inter[0] = (R1 - R0)/(2.*denom); //one solution
  1818. Ninter = 1;
  1819. }
  1820. }
  1821. else
  1822. {
  1823. double D2 = D*D;
  1824. double Q = 0.5*(R1-R0-D2);
  1825. double X = x0 - x1;
  1826. double A = X*X - D2;
  1827. double B = Q*X + D2*x0;
  1828. double C = Q*Q - D2*R0;
  1829. if (std::abs(A)<local_small_epsilon) //if A == 0, linear equation
  1830. {
  1831. if(std::abs(B)>local_small_epsilon)
  1832. {
  1833. inter[0] = -C/B; //one solution
  1834. Ninter = 1;
  1835. }
  1836. }
  1837. else
  1838. {
  1839. double det = B*B-A*C;
  1840. if(det>local_small_epsilon*local_small_epsilon) //two roots
  1841. {
  1842. det = sqrt(det);
  1843. if(A>0.0) //make sure that the roots are ordered
  1844. {
  1845. inter[0] = (-B - det)/A;
  1846. inter[1] = (-B + det)/A;
  1847. }
  1848. else
  1849. {
  1850. inter[0] = (-B + det)/A;
  1851. inter[1] = (-B - det)/A;
  1852. }
  1853. if(inter[1] - inter[0] > local_small_epsilon)
  1854. {
  1855. Ninter = 2;
  1856. }
  1857. else
  1858. {
  1859. Ninter = 1;
  1860. }
  1861. }
  1862. else if(det>=0.0) //single root
  1863. {
  1864. inter[0] = -B/A;
  1865. Ninter = 1;
  1866. }
  1867. }
  1868. }
  1869. //---------------------------find possible intervals---------------------------------------
  1870. double left = std::max(zero->start(), one->start()); //define left and right boundaries of the intersection of the intervals
  1871. double right = std::min(zero->stop(), one->stop());
  1872. double good_start[4]; //points of intersection within the (left, right) limits +"left" + "right"
  1873. good_start[0] = left;
  1874. unsigned char Ngood_start=1; //number of the points of the intersection
  1875. for(unsigned char i=0; i<Ninter; ++i) //for all points of intersection
  1876. {
  1877. double x = inter[i];
  1878. if(x > left + local_epsilon && x < right - local_epsilon)
  1879. {
  1880. good_start[Ngood_start++] = x;
  1881. }
  1882. }
  1883. good_start[Ngood_start++] = right;
  1884. MapType mid_map[3];
  1885. for(unsigned char i=0; i<Ngood_start-1; ++i)
  1886. {
  1887. double mid = (good_start[i] + good_start[i+1])*0.5;
  1888. mid_map[i] = zero->signal(mid) <= one->signal(mid) ? OLD : NEW;
  1889. }
  1890. //-----------------------------------output----------------------------------
  1891. N = 0;
  1892. if(zero->start() < left - local_epsilon) //additional "zero" interval
  1893. {
  1894. if(mid_map[0] == OLD) //first interval in the map is already the old one
  1895. {
  1896. good_start[0] = zero->start();
  1897. }
  1898. else
  1899. {
  1900. map[N] = OLD; //"zero" interval
  1901. start[N++] = zero->start();
  1902. }
  1903. }
  1904. for(long i=0;i<Ngood_start-1;++i) //for all intervals
  1905. {
  1906. MapType current_map = mid_map[i];
  1907. if(N==0 || map[N-1] != current_map)
  1908. {
  1909. map[N] = current_map;
  1910. start[N++] = good_start[i];
  1911. }
  1912. }
  1913. if(zero->stop() > one->stop() + local_epsilon)
  1914. {
  1915. if(N==0 || map[N-1] == NEW)
  1916. {
  1917. map[N] = OLD; //"zero" interval
  1918. start[N++] = one->stop();
  1919. }
  1920. }
  1921. start[0] = zero->start(); // just to make sure that epsilons do not damage anything
  1922. //start[N] = zero->stop();
  1923. return N;
  1924. }
  1925. inline void GeodesicAlgorithmExact::initialize_propagation_data()
  1926. {
  1927. clear();
  1928. IntervalWithStop candidate;
  1929. std::vector<edge_pointer> edges_visible_from_source;
  1930. for(unsigned i=0; i<m_sources.size(); ++i) //for all edges adjacent to the starting vertex
  1931. {
  1932. SurfacePoint* source = &m_sources[i];
  1933. edges_visible_from_source.clear();
  1934. list_edges_visible_from_source(source->base_element(),
  1935. edges_visible_from_source);
  1936. for(unsigned j=0; j<edges_visible_from_source.size(); ++j)
  1937. {
  1938. edge_pointer e = edges_visible_from_source[j];
  1939. candidate.initialize(e, source, i);
  1940. candidate.stop() = e->length();
  1941. candidate.compute_min_distance(candidate.stop());
  1942. candidate.direction() = Interval::FROM_SOURCE;
  1943. update_list_and_queue(interval_list(e), &candidate, 1);
  1944. }
  1945. }
  1946. }
  1947. inline void GeodesicAlgorithmExact::propagate(std::vector<SurfacePoint>& sources,
  1948. double max_propagation_distance, //propagation algorithm stops after reaching the certain distance from the source
  1949. std::vector<SurfacePoint>* stop_points)
  1950. {
  1951. set_stop_conditions(stop_points, max_propagation_distance);
  1952. set_sources(sources);
  1953. initialize_propagation_data();
  1954. clock_t start = clock();
  1955. unsigned satisfied_index = 0;
  1956. m_iterations = 0; //for statistics
  1957. m_queue_max_size = 0;
  1958. IntervalWithStop candidates[2];
  1959. while(!m_queue.empty())
  1960. {
  1961. m_queue_max_size = std::max(static_cast<unsigned int>(m_queue.size()), m_queue_max_size);
  1962. unsigned const check_period = 10;
  1963. if(++m_iterations % check_period == 0) //check if we covered all required vertices
  1964. {
  1965. if (check_stop_conditions(satisfied_index))
  1966. {
  1967. break;
  1968. }
  1969. }
  1970. interval_pointer min_interval = *m_queue.begin();
  1971. m_queue.erase(m_queue.begin());
  1972. edge_pointer edge = min_interval->edge();
  1973. //list_pointer list = interval_list(edge);
  1974. assert(min_interval->d() < GEODESIC_INF);
  1975. bool const first_interval = min_interval->start() == 0.0;
  1976. //bool const last_interval = min_interval->stop() == edge->length();
  1977. bool const last_interval = min_interval->next() == NULL;
  1978. bool const turn_left = edge->v0()->saddle_or_boundary();
  1979. bool const turn_right = edge->v1()->saddle_or_boundary();
  1980. for(unsigned i=0; i<edge->adjacent_faces().size(); ++i) //two possible faces to propagate
  1981. {
  1982. if(!edge->is_boundary()) //just in case, always propagate boundary edges
  1983. {
  1984. if((i == 0 && min_interval->direction() == Interval::FROM_FACE_0) ||
  1985. (i == 1 && min_interval->direction() == Interval::FROM_FACE_1))
  1986. {
  1987. continue;
  1988. }
  1989. }
  1990. face_pointer face = edge->adjacent_faces()[i]; //if we come from 1, go to 2
  1991. edge_pointer next_edge = face->next_edge(edge,edge->v0());
  1992. unsigned num_propagated = compute_propagated_parameters(min_interval->pseudo_x(),
  1993. min_interval->pseudo_y(),
  1994. min_interval->d(), //parameters of the interval
  1995. min_interval->start(),
  1996. min_interval->stop(), //start/end of the interval
  1997. face->vertex_angle(edge->v0()), //corner angle
  1998. next_edge->length(), //length of the new edge
  1999. first_interval, //if it is the first interval on the edge
  2000. last_interval,
  2001. turn_left,
  2002. turn_right,
  2003. candidates); //if it is the last interval on the edge
  2004. bool propagate_to_right = true;
  2005. if(num_propagated)
  2006. {
  2007. if(candidates[num_propagated-1].stop() != next_edge->length())
  2008. {
  2009. propagate_to_right = false;
  2010. }
  2011. bool const invert = next_edge->v0()->id() != edge->v0()->id(); //if the origins coinside, do not invert intervals
  2012. construct_propagated_intervals(invert, //do not inverse
  2013. next_edge,
  2014. face,
  2015. candidates,
  2016. num_propagated,
  2017. min_interval);
  2018. update_list_and_queue(interval_list(next_edge),
  2019. candidates,
  2020. num_propagated);
  2021. }
  2022. if(propagate_to_right)
  2023. {
  2024. //propogation to the right edge
  2025. double length = edge->length();
  2026. next_edge = face->next_edge(edge,edge->v1());
  2027. num_propagated = compute_propagated_parameters(length - min_interval->pseudo_x(),
  2028. min_interval->pseudo_y(),
  2029. min_interval->d(), //parameters of the interval
  2030. length - min_interval->stop(),
  2031. length - min_interval->start(), //start/end of the interval
  2032. face->vertex_angle(edge->v1()), //corner angle
  2033. next_edge->length(), //length of the new edge
  2034. last_interval, //if it is the first interval on the edge
  2035. first_interval,
  2036. turn_right,
  2037. turn_left,
  2038. candidates); //if it is the last interval on the edge
  2039. if(num_propagated)
  2040. {
  2041. bool const invert = next_edge->v0()->id() != edge->v1()->id(); //if the origins coinside, do not invert intervals
  2042. construct_propagated_intervals(invert, //do not inverse
  2043. next_edge,
  2044. face,
  2045. candidates,
  2046. num_propagated,
  2047. min_interval);
  2048. update_list_and_queue(interval_list(next_edge),
  2049. candidates,
  2050. num_propagated);
  2051. }
  2052. }
  2053. }
  2054. }
  2055. m_propagation_distance_stopped = m_queue.empty() ? GEODESIC_INF : (*m_queue.begin())->min();
  2056. clock_t stop = clock();
  2057. m_time_consumed = (static_cast<double>(stop)-static_cast<double>(start))/CLOCKS_PER_SEC;
  2058. /* for(unsigned i=0; i<m_edge_interval_lists.size(); ++i)
  2059. {
  2060. list_pointer list = &m_edge_interval_lists[i];
  2061. interval_pointer p = list->first();
  2062. assert(p->start() == 0.0);
  2063. while(p->next())
  2064. {
  2065. assert(p->stop() == p->next()->start());
  2066. assert(p->d() < GEODESIC_INF);
  2067. p = p->next();
  2068. }
  2069. }*/
  2070. }
  2071. inline bool GeodesicAlgorithmExact::check_stop_conditions(unsigned& index)
  2072. {
  2073. double queue_distance = (*m_queue.begin())->min();
  2074. if(queue_distance < stop_distance())
  2075. {
  2076. return false;
  2077. }
  2078. while(index < m_stop_vertices.size())
  2079. {
  2080. vertex_pointer v = m_stop_vertices[index].first;
  2081. edge_pointer edge = v->adjacent_edges()[0]; //take any edge
  2082. double distance = edge->v0()->id() == v->id() ?
  2083. interval_list(edge)->signal(0.0) :
  2084. interval_list(edge)->signal(edge->length());
  2085. if(queue_distance < distance + m_stop_vertices[index].second)
  2086. {
  2087. return false;
  2088. }
  2089. ++index;
  2090. }
  2091. return true;
  2092. }
  2093. inline void GeodesicAlgorithmExact::update_list_and_queue(list_pointer list,
  2094. IntervalWithStop* candidates, //up to two candidates
  2095. unsigned num_candidates)
  2096. {
  2097. assert(num_candidates <= 2);
  2098. //assert(list->first() != NULL);
  2099. edge_pointer edge = list->edge();
  2100. double const local_epsilon = SMALLEST_INTERVAL_RATIO * edge->length();
  2101. if(list->first() == NULL)
  2102. {
  2103. interval_pointer* p = &list->first();
  2104. IntervalWithStop* first;
  2105. IntervalWithStop* second;
  2106. if(num_candidates == 1)
  2107. {
  2108. first = candidates;
  2109. second = candidates;
  2110. first->compute_min_distance(first->stop());
  2111. }
  2112. else
  2113. {
  2114. if(candidates->start() <= (candidates+1)->start())
  2115. {
  2116. first = candidates;
  2117. second = candidates+1;
  2118. }
  2119. else
  2120. {
  2121. first = candidates+1;
  2122. second = candidates;
  2123. }
  2124. assert(first->stop() == second->start());
  2125. first->compute_min_distance(first->stop());
  2126. second->compute_min_distance(second->stop());
  2127. }
  2128. if(first->start() > 0.0)
  2129. {
  2130. *p = m_memory_allocator.allocate();
  2131. (*p)->initialize(edge);
  2132. p = &(*p)->next();
  2133. }
  2134. *p = m_memory_allocator.allocate();
  2135. memcpy(*p,first,sizeof(Interval));
  2136. m_queue.insert(*p);
  2137. if(num_candidates == 2)
  2138. {
  2139. p = &(*p)->next();
  2140. *p = m_memory_allocator.allocate();
  2141. memcpy(*p,second,sizeof(Interval));
  2142. m_queue.insert(*p);
  2143. }
  2144. if(second->stop() < edge->length())
  2145. {
  2146. p = &(*p)->next();
  2147. *p = m_memory_allocator.allocate();
  2148. (*p)->initialize(edge);
  2149. (*p)->start() = second->stop();
  2150. }
  2151. else
  2152. {
  2153. (*p)->next() = NULL;
  2154. }
  2155. return;
  2156. }
  2157. bool propagate_flag;
  2158. for(unsigned i=0; i<num_candidates; ++i) //for all new intervals
  2159. {
  2160. IntervalWithStop* q = &candidates[i];
  2161. interval_pointer previous = NULL;
  2162. interval_pointer p = list->first();
  2163. assert(p->start() == 0.0);
  2164. while(p != NULL && p->stop() - local_epsilon < q->start())
  2165. {
  2166. p = p->next();
  2167. }
  2168. while(p != NULL && p->start() < q->stop() - local_epsilon) //go through all old intervals
  2169. {
  2170. unsigned const N = intersect_intervals(p, q); //interset two intervals
  2171. if(N == 1)
  2172. {
  2173. if(map[0]==OLD) //if "p" is always better, we do not need to update anything)
  2174. {
  2175. if(previous) //close previous interval and put in into the queue
  2176. {
  2177. previous->next() = p;
  2178. previous->compute_min_distance(p->start());
  2179. m_queue.insert(previous);
  2180. previous = NULL;
  2181. }
  2182. p = p->next();
  2183. }
  2184. else if(previous) //extend previous interval to cover everything; remove p
  2185. {
  2186. previous->next() = p->next();
  2187. erase_from_queue(p);
  2188. m_memory_allocator.deallocate(p);
  2189. p = previous->next();
  2190. }
  2191. else //p becomes "previous"
  2192. {
  2193. previous = p;
  2194. interval_pointer next = p->next();
  2195. erase_from_queue(p);
  2196. memcpy(previous,q,sizeof(Interval));
  2197. previous->start() = start[0];
  2198. previous->next() = next;
  2199. p = next;
  2200. }
  2201. continue;
  2202. }
  2203. //update_flag = true;
  2204. Interval swap(*p); //used for swapping information
  2205. propagate_flag = erase_from_queue(p);
  2206. for(unsigned j=1; j<N; ++j) //no memory is needed for the first one
  2207. {
  2208. i_new[j] = m_memory_allocator.allocate(); //create new intervals
  2209. }
  2210. if(map[0]==OLD) //finish previous, if any
  2211. {
  2212. if(previous)
  2213. {
  2214. previous->next() = p;
  2215. previous->compute_min_distance(previous->stop());
  2216. m_queue.insert(previous);
  2217. previous = NULL;
  2218. }
  2219. i_new[0] = p;
  2220. p->next() = i_new[1];
  2221. p->start() = start[0];
  2222. }
  2223. else if(previous) //extend previous interval to cover everything; remove p
  2224. {
  2225. i_new[0] = previous;
  2226. previous->next() = i_new[1];
  2227. m_memory_allocator.deallocate(p);
  2228. previous = NULL;
  2229. }
  2230. else //p becomes "previous"
  2231. {
  2232. i_new[0] = p;
  2233. memcpy(p,q,sizeof(Interval));
  2234. p->next() = i_new[1];
  2235. p->start() = start[0];
  2236. }
  2237. assert(!previous);
  2238. for(unsigned j=1; j<N; ++j)
  2239. {
  2240. interval_pointer current_interval = i_new[j];
  2241. if(map[j] == OLD)
  2242. {
  2243. memcpy(current_interval,&swap,sizeof(Interval));
  2244. }
  2245. else
  2246. {
  2247. memcpy(current_interval,q,sizeof(Interval));
  2248. }
  2249. if(j == N-1)
  2250. {
  2251. current_interval->next() = swap.next();
  2252. }
  2253. else
  2254. {
  2255. current_interval->next() = i_new[j+1];
  2256. }
  2257. current_interval->start() = start[j];
  2258. }
  2259. for(unsigned j=0; j<N; ++j) //find "min" and add the intervals to the queue
  2260. {
  2261. if(j==N-1 && map[j]==NEW)
  2262. {
  2263. previous = i_new[j];
  2264. }
  2265. else
  2266. {
  2267. interval_pointer current_interval = i_new[j];
  2268. current_interval->compute_min_distance(current_interval->stop()); //compute minimal distance
  2269. if(map[j]==NEW || (map[j]==OLD && propagate_flag))
  2270. {
  2271. m_queue.insert(current_interval);
  2272. }
  2273. }
  2274. }
  2275. p = swap.next();
  2276. }
  2277. if(previous) //close previous interval and put in into the queue
  2278. {
  2279. previous->compute_min_distance(previous->stop());
  2280. m_queue.insert(previous);
  2281. previous = NULL;
  2282. }
  2283. }
  2284. }
  2285. inline unsigned GeodesicAlgorithmExact::compute_propagated_parameters(double pseudo_x,
  2286. double pseudo_y,
  2287. double d, //parameters of the interval
  2288. double begin,
  2289. double end, //start/end of the interval
  2290. double alpha, //corner angle
  2291. double L, //length of the new edge
  2292. bool first_interval, //if it is the first interval on the edge
  2293. bool last_interval,
  2294. bool turn_left,
  2295. bool turn_right,
  2296. IntervalWithStop* candidates) //if it is the last interval on the edge
  2297. {
  2298. assert(pseudo_y<=0.0);
  2299. assert(d<GEODESIC_INF/10.0);
  2300. assert(begin<=end);
  2301. assert(first_interval ? (begin == 0.0) : true);
  2302. IntervalWithStop* p = candidates;
  2303. if(std::abs(pseudo_y) <= 1e-30) //pseudo-source is on the edge
  2304. {
  2305. if(first_interval && pseudo_x <= 0.0)
  2306. {
  2307. p->start() = 0.0;
  2308. p->stop() = L;
  2309. p->d() = d - pseudo_x;
  2310. p->pseudo_x() = 0.0;
  2311. p->pseudo_y() = 0.0;
  2312. return 1;
  2313. }
  2314. else if(last_interval && pseudo_x >= end)
  2315. {
  2316. p->start() = 0.0;
  2317. p->stop() = L;
  2318. p->d() = d + pseudo_x-end;
  2319. p->pseudo_x() = end*cos(alpha);
  2320. p->pseudo_y() = -end*sin(alpha);
  2321. return 1;
  2322. }
  2323. else if(pseudo_x >= begin && pseudo_x <= end)
  2324. {
  2325. p->start() = 0.0;
  2326. p->stop() = L;
  2327. p->d() = d;
  2328. p->pseudo_x() = pseudo_x*cos(alpha);
  2329. p->pseudo_y() = -pseudo_x*sin(alpha);
  2330. return 1;
  2331. }
  2332. else
  2333. {
  2334. return 0;
  2335. }
  2336. }
  2337. double sin_alpha = sin(alpha);
  2338. double cos_alpha = cos(alpha);
  2339. //important: for the first_interval, this function returns zero only if the new edge is "visible" from the source
  2340. //if the new edge can be covered only after turn_over, the value is negative (-1.0)
  2341. double L1 = compute_positive_intersection(begin,
  2342. pseudo_x,
  2343. pseudo_y,
  2344. sin_alpha,
  2345. cos_alpha);
  2346. if(L1 < 0 || L1 >= L)
  2347. {
  2348. if(first_interval && turn_left)
  2349. {
  2350. p->start() = 0.0;
  2351. p->stop() = L;
  2352. p->d() = d + sqrt(pseudo_x*pseudo_x + pseudo_y*pseudo_y);
  2353. p->pseudo_y() = 0.0;
  2354. p->pseudo_x() = 0.0;
  2355. return 1;
  2356. }
  2357. else
  2358. {
  2359. return 0;
  2360. }
  2361. }
  2362. double L2 = compute_positive_intersection(end,
  2363. pseudo_x,
  2364. pseudo_y,
  2365. sin_alpha,
  2366. cos_alpha);
  2367. if(L2 < 0 || L2 >= L)
  2368. {
  2369. p->start() = L1;
  2370. p->stop() = L;
  2371. p->d() = d;
  2372. p->pseudo_x() = cos_alpha*pseudo_x + sin_alpha*pseudo_y;
  2373. p->pseudo_y() = -sin_alpha*pseudo_x + cos_alpha*pseudo_y;
  2374. return 1;
  2375. }
  2376. p->start() = L1;
  2377. p->stop() = L2;
  2378. p->d() = d;
  2379. p->pseudo_x() = cos_alpha*pseudo_x + sin_alpha*pseudo_y;
  2380. p->pseudo_y() = -sin_alpha*pseudo_x + cos_alpha*pseudo_y;
  2381. assert(p->pseudo_y() <= 0.0);
  2382. if(!(last_interval && turn_right))
  2383. {
  2384. return 1;
  2385. }
  2386. else
  2387. {
  2388. p = candidates + 1;
  2389. p->start() = L2;
  2390. p->stop() = L;
  2391. double dx = pseudo_x - end;
  2392. p->d() = d + sqrt(dx*dx + pseudo_y*pseudo_y);
  2393. p->pseudo_x() = end*cos_alpha;
  2394. p->pseudo_y() = -end*sin_alpha;
  2395. return 2;
  2396. }
  2397. }
  2398. inline void GeodesicAlgorithmExact::construct_propagated_intervals(bool invert,
  2399. edge_pointer edge,
  2400. face_pointer face, //constructs iNew from the rest of the data
  2401. IntervalWithStop* candidates,
  2402. unsigned& num_candidates,
  2403. interval_pointer source_interval) //up to two candidates
  2404. {
  2405. double edge_length = edge->length();
  2406. double local_epsilon = SMALLEST_INTERVAL_RATIO * edge_length;
  2407. //kill very small intervals in order to avoid precision problems
  2408. if(num_candidates == 2)
  2409. {
  2410. double start = std::min(candidates->start(), (candidates+1)->start());
  2411. double stop = std::max(candidates->stop(), (candidates+1)->stop());
  2412. if(candidates->stop()-candidates->start() < local_epsilon) // kill interval 0
  2413. {
  2414. *candidates = *(candidates+1);
  2415. num_candidates = 1;
  2416. candidates->start() = start;
  2417. candidates->stop() = stop;
  2418. }
  2419. else if ((candidates+1)->stop() - (candidates+1)->start() < local_epsilon)
  2420. {
  2421. num_candidates = 1;
  2422. candidates->start() = start;
  2423. candidates->stop() = stop;
  2424. }
  2425. }
  2426. IntervalWithStop* first;
  2427. IntervalWithStop* second;
  2428. if(num_candidates == 1)
  2429. {
  2430. first = candidates;
  2431. second = candidates;
  2432. }
  2433. else
  2434. {
  2435. if(candidates->start() <= (candidates+1)->start())
  2436. {
  2437. first = candidates;
  2438. second = candidates+1;
  2439. }
  2440. else
  2441. {
  2442. first = candidates+1;
  2443. second = candidates;
  2444. }
  2445. assert(first->stop() == second->start());
  2446. }
  2447. if(first->start() < local_epsilon)
  2448. {
  2449. first->start() = 0.0;
  2450. }
  2451. if(edge_length - second->stop() < local_epsilon)
  2452. {
  2453. second->stop() = edge_length;
  2454. }
  2455. //invert intervals if necessary; fill missing data and set pointers correctly
  2456. Interval::DirectionType direction = edge->adjacent_faces()[0]->id() == face->id() ?
  2457. Interval::FROM_FACE_0 :
  2458. Interval::FROM_FACE_1;
  2459. if(!invert) //in this case everything is straighforward, we do not have to invert the intervals
  2460. {
  2461. for(unsigned i=0; i<num_candidates; ++i)
  2462. {
  2463. IntervalWithStop* p = candidates + i;
  2464. p->next() = (i == num_candidates - 1) ? NULL : candidates + i + 1;
  2465. p->edge() = edge;
  2466. p->direction() = direction;
  2467. p->source_index() = source_interval->source_index();
  2468. p->min() = 0.0; //it will be changed later on
  2469. assert(p->start() < p->stop());
  2470. }
  2471. }
  2472. else //now we have to invert the intervals
  2473. {
  2474. for(unsigned i=0; i<num_candidates; ++i)
  2475. {
  2476. IntervalWithStop* p = candidates + i;
  2477. p->next() = (i == 0) ? NULL : candidates + i - 1;
  2478. p->edge() = edge;
  2479. p->direction() = direction;
  2480. p->source_index() = source_interval->source_index();
  2481. double length = edge_length;
  2482. p->pseudo_x() = length - p->pseudo_x();
  2483. double start = length - p->stop();
  2484. p->stop() = length - p->start();
  2485. p->start() = start;
  2486. p->min() = 0;
  2487. assert(p->start() < p->stop());
  2488. assert(p->start() >= 0.0);
  2489. assert(p->stop() <= edge->length());
  2490. }
  2491. }
  2492. }
  2493. inline unsigned GeodesicAlgorithmExact::best_source(SurfacePoint& point, //quickly find what source this point belongs to and what is the distance to this source
  2494. double& best_source_distance)
  2495. {
  2496. double best_interval_position;
  2497. unsigned best_source_index;
  2498. best_first_interval(point,
  2499. best_source_distance,
  2500. best_interval_position,
  2501. best_source_index);
  2502. return best_source_index;
  2503. }
  2504. inline interval_pointer GeodesicAlgorithmExact::best_first_interval(SurfacePoint& point,
  2505. double& best_total_distance,
  2506. double& best_interval_position,
  2507. unsigned& best_source_index)
  2508. {
  2509. assert(point.type() != UNDEFINED_POINT);
  2510. interval_pointer best_interval = NULL;
  2511. best_total_distance = GEODESIC_INF;
  2512. if(point.type() == EDGE)
  2513. {
  2514. edge_pointer e = static_cast<edge_pointer>(point.base_element());
  2515. list_pointer list = interval_list(e);
  2516. best_interval_position = point.distance(e->v0());
  2517. best_interval = list->covering_interval(best_interval_position);
  2518. if(best_interval)
  2519. {
  2520. //assert(best_interval && best_interval->d() < GEODESIC_INF);
  2521. best_total_distance = best_interval->signal(best_interval_position);
  2522. best_source_index = best_interval->source_index();
  2523. }
  2524. }
  2525. else if(point.type() == FACE)
  2526. {
  2527. face_pointer f = static_cast<face_pointer>(point.base_element());
  2528. for(unsigned i=0; i<3; ++i)
  2529. {
  2530. edge_pointer e = f->adjacent_edges()[i];
  2531. list_pointer list = interval_list(e);
  2532. double offset;
  2533. double distance;
  2534. interval_pointer interval;
  2535. list->find_closest_point(&point,
  2536. offset,
  2537. distance,
  2538. interval);
  2539. if(interval && distance < best_total_distance)
  2540. {
  2541. best_interval = interval;
  2542. best_total_distance = distance;
  2543. best_interval_position = offset;
  2544. best_source_index = interval->source_index();
  2545. }
  2546. }
  2547. //check for all sources that might be located inside this face
  2548. SortedSources::sorted_iterator_pair local_sources = m_sources.sources(f);
  2549. for(SortedSources::sorted_iterator it=local_sources.first; it != local_sources.second; ++it)
  2550. {
  2551. SurfacePointWithIndex* source = *it;
  2552. double distance = point.distance(source);
  2553. if(distance < best_total_distance)
  2554. {
  2555. best_interval = NULL;
  2556. best_total_distance = distance;
  2557. best_interval_position = 0.0;
  2558. best_source_index = source->index();
  2559. }
  2560. }
  2561. }
  2562. else if(point.type() == VERTEX)
  2563. {
  2564. vertex_pointer v = static_cast<vertex_pointer>(point.base_element());
  2565. for(unsigned i=0; i<v->adjacent_edges().size(); ++i)
  2566. {
  2567. edge_pointer e = v->adjacent_edges()[i];
  2568. list_pointer list = interval_list(e);
  2569. double position = e->v0()->id() == v->id() ? 0.0 : e->length();
  2570. interval_pointer interval = list->covering_interval(position);
  2571. if(interval)
  2572. {
  2573. double distance = interval->signal(position);
  2574. if(distance < best_total_distance)
  2575. {
  2576. best_interval = interval;
  2577. best_total_distance = distance;
  2578. best_interval_position = position;
  2579. best_source_index = interval->source_index();
  2580. }
  2581. }
  2582. }
  2583. }
  2584. if(best_total_distance > m_propagation_distance_stopped) //result is unreliable
  2585. {
  2586. best_total_distance = GEODESIC_INF;
  2587. return NULL;
  2588. }
  2589. else
  2590. {
  2591. return best_interval;
  2592. }
  2593. }
  2594. inline void GeodesicAlgorithmExact::trace_back(SurfacePoint& destination, //trace back piecewise-linear path
  2595. std::vector<SurfacePoint>& path)
  2596. {
  2597. path.clear();
  2598. double best_total_distance;
  2599. double best_interval_position;
  2600. unsigned source_index = std::numeric_limits<unsigned>::max();
  2601. interval_pointer best_interval = best_first_interval(destination,
  2602. best_total_distance,
  2603. best_interval_position,
  2604. source_index);
  2605. if(best_total_distance >= GEODESIC_INF/2.0) //unable to find the right path
  2606. {
  2607. return;
  2608. }
  2609. path.push_back(destination);
  2610. if(best_interval) //if we did not hit the face source immediately
  2611. {
  2612. std::vector<edge_pointer> possible_edges;
  2613. possible_edges.reserve(10);
  2614. while(visible_from_source(path.back()) < 0) //while this point is not in the direct visibility of some source (if we are inside the FACE, we obviously hit the source)
  2615. {
  2616. SurfacePoint& q = path.back();
  2617. possible_traceback_edges(q, possible_edges);
  2618. interval_pointer interval;
  2619. double total_distance;
  2620. double position;
  2621. best_point_on_the_edge_set(q,
  2622. possible_edges,
  2623. interval,
  2624. total_distance,
  2625. position);
  2626. //std::cout << total_distance + length(path) << std::endl;
  2627. assert(total_distance<GEODESIC_INF);
  2628. source_index = interval->source_index();
  2629. edge_pointer e = interval->edge();
  2630. double local_epsilon = SMALLEST_INTERVAL_RATIO*e->length();
  2631. if(position < local_epsilon)
  2632. {
  2633. path.push_back(SurfacePoint(e->v0()));
  2634. }
  2635. else if(position > e->length()-local_epsilon)
  2636. {
  2637. path.push_back(SurfacePoint(e->v1()));
  2638. }
  2639. else
  2640. {
  2641. double normalized_position = position/e->length();
  2642. path.push_back(SurfacePoint(e, normalized_position));
  2643. }
  2644. }
  2645. }
  2646. SurfacePoint& source = static_cast<SurfacePoint&>(m_sources[source_index]);
  2647. if(path.back().distance(&source) > 0)
  2648. {
  2649. path.push_back(source);
  2650. }
  2651. }
  2652. inline void GeodesicAlgorithmExact::print_statistics()
  2653. {
  2654. GeodesicAlgorithmBase::print_statistics();
  2655. unsigned interval_counter = 0;
  2656. for(unsigned i=0; i<m_edge_interval_lists.size(); ++i)
  2657. {
  2658. interval_counter += m_edge_interval_lists[i].number_of_intervals();
  2659. }
  2660. double intervals_per_edge = (double)interval_counter/(double)m_edge_interval_lists.size();
  2661. double memory = m_edge_interval_lists.size()*sizeof(IntervalList) +
  2662. interval_counter*sizeof(Interval);
  2663. std::cout << "uses about " << memory/1e6 << "Mb of memory" <<std::endl;
  2664. std::cout << interval_counter << " total intervals, or "
  2665. << intervals_per_edge << " intervals per edge"
  2666. << std::endl;
  2667. std::cout << "maximum interval queue size is " << m_queue_max_size << std::endl;
  2668. std::cout << "number of interval propagations is " << m_iterations << std::endl;
  2669. }
  2670. } //geodesic
  2671. }
  2672. template <
  2673. typename DerivedV,
  2674. typename DerivedF,
  2675. typename DerivedVS,
  2676. typename DerivedFS,
  2677. typename DerivedVT,
  2678. typename DerivedFT,
  2679. typename DerivedD>
  2680. IGL_INLINE void igl::exact_geodesic(
  2681. const Eigen::MatrixBase<DerivedV> &V,
  2682. const Eigen::MatrixBase<DerivedF> &F,
  2683. const Eigen::MatrixBase<DerivedVS> &VS,
  2684. const Eigen::MatrixBase<DerivedFS> &FS,
  2685. const Eigen::MatrixBase<DerivedVT> &VT,
  2686. const Eigen::MatrixBase<DerivedFT> &FT,
  2687. Eigen::PlainObjectBase<DerivedD> &D)
  2688. {
  2689. assert((V.cols() == 3 || V.cols() == 2) && F.cols() == 3 && "Only support 2D/3D triangle mesh");
  2690. std::vector<typename DerivedV::Scalar> points(V.rows() * 3);
  2691. std::vector<typename DerivedF::Scalar> faces(F.rows() * F.cols());
  2692. for (int i = 0; i < points.size(); i++)
  2693. {
  2694. // Append 0s for 2D input
  2695. points[i] = ((i%3)<2 || V.cols()==3) ? V(i / 3, i % 3) : 0.0;
  2696. }
  2697. for (int i = 0; i < faces.size(); i++)
  2698. {
  2699. faces[i] = F(i / 3, i % 3);
  2700. }
  2701. igl::geodesic::Mesh mesh;
  2702. mesh.initialize_mesh_data(points, faces);
  2703. igl::geodesic::GeodesicAlgorithmExact exact_algorithm(&mesh);
  2704. std::vector<igl::geodesic::SurfacePoint> source;
  2705. source.reserve(VS.rows() + FS.rows());
  2706. // Vertex sources
  2707. for(int i = 0;i < VS.rows(); i++)
  2708. {
  2709. for(int j = 0;j < VS.cols(); j++)
  2710. {
  2711. source.emplace_back(&mesh.vertices()[VS(i, j)]);
  2712. }
  2713. }
  2714. // Face Sources
  2715. for(int i = 0;i < FS.rows(); i++)
  2716. {
  2717. for(int j = 0;j < FS.cols(); j++)
  2718. {
  2719. source.emplace_back(&mesh.faces()[FS(i, j)]);
  2720. }
  2721. }
  2722. std::vector<igl::geodesic::SurfacePoint> target;
  2723. target.reserve(VT.rows() + FT.rows());
  2724. //Vertex targets
  2725. for(int i = 0;i < VT.rows(); i++)
  2726. {
  2727. for(int j = 0;j < VT.cols(); j++)
  2728. {
  2729. target.emplace_back(&mesh.vertices()[VT(i, j)]);
  2730. }
  2731. }
  2732. // Face targets
  2733. for(int i = 0;i < FT.rows(); i++)
  2734. {
  2735. for(int j = 0;j < FT.cols(); j++)
  2736. {
  2737. target.emplace_back(&mesh.faces()[FT(i, j)]);
  2738. }
  2739. }
  2740. exact_algorithm.propagate(source);
  2741. std::vector<igl::geodesic::SurfacePoint> path;
  2742. D.resize(target.size());
  2743. for (int i = 0; i < target.size(); i++)
  2744. {
  2745. exact_algorithm.trace_back(target[i], path);
  2746. D(i) = igl::geodesic::length(path);
  2747. }
  2748. }
  2749. #ifdef IGL_STATIC_LIBRARY
  2750. template void igl::exact_geodesic<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const &, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1>> &);
  2751. #endif