exact_geodesic.cpp 78 KB

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