├── .gitignore ├── example-2d ├── addons.make └── src │ └── main.cpp ├── example-3d ├── addons.make └── src │ └── main.cpp ├── example-data ├── addons.make ├── bin │ └── data │ │ └── data.tsv └── src │ └── main.cpp ├── example-mosaic ├── addons.make └── src │ └── main.cpp ├── license.md ├── readme.md └── src ├── jv ├── lap.cpp └── lap.h ├── ofxAssignment.cpp └── ofxAssignment.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.depend 2 | *.layout 3 | *.mode*v3 4 | *.pbxuser 5 | *.app* 6 | *.DS_* 7 | *.xcworkspacedata 8 | xcuserdata/ 9 | project.xcworkspace 10 | 11 | *.opensdf 12 | *.sdf 13 | *.suo 14 | *.ipch 15 | 16 | .svn/ 17 | obj/ 18 | bin/ 19 | build/ 20 | !data/ 21 | 22 | *.xcodeproj 23 | *.xcconfig 24 | config.make 25 | *.plist 26 | Makefile -------------------------------------------------------------------------------- /example-2d/addons.make: -------------------------------------------------------------------------------- 1 | ofxAssignment 2 | -------------------------------------------------------------------------------- /example-2d/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "ofxAssignment.h" 3 | 4 | class ofApp : public ofBaseApp { 5 | public: 6 | ofxAssignment solver; 7 | vector initial, grid; 8 | void setup() { 9 | int side = 32; 10 | int n = side * side; 11 | 12 | // first, generate some data on a random walk modulo one 13 | initial.clear(); 14 | ofVec2f cur; 15 | ofSeedRandom(ofGetSystemTimeMicros()); 16 | for(int i = 0; i < n; i++) { 17 | cur += ofVec2f(ofRandomf(), ofRandomf()) * .01; 18 | cur.x = fmodf(cur.x, 1); 19 | cur.y = fmodf(cur.y, 1); 20 | initial.push_back(cur); 21 | } 22 | 23 | // then build the grid 24 | grid = makeGrid(side, side); 25 | 26 | // and finally, match the grid to the data 27 | auto start = ofGetElapsedTimeMillis(); 28 | grid = solver.match(initial, grid); 29 | auto stop = ofGetElapsedTimeMillis(); 30 | 31 | // 625 points in 64ms 32 | // 1024 points in 211ms 33 | // 4096 points in 8841ms 34 | cout << grid.size() << " points in " << (stop - start) << "ms" << endl; 35 | 36 | ofBackground(0); 37 | glPointSize(6); 38 | } 39 | void draw() { 40 | ofMesh mesh; 41 | mesh.setMode(OF_PRIMITIVE_POINTS); 42 | int n = initial.size(); 43 | float t = ofMap(cos(ofGetElapsedTimef()), -1, 1, 0, 1); 44 | ofSeedRandom(0); 45 | for(int i = 0; i < n; i++) { 46 | ofVec2f v = grid[i] * t + initial[i] * (1 - t); 47 | mesh.addVertex(ofVec3f(v)); 48 | mesh.addColor(ofFloatColor(1, initial[i].x, initial[i].y)); 49 | } 50 | float padding = 128; 51 | float scale = ofGetWidth() - 2 * padding; 52 | ofTranslate(padding, padding); 53 | ofScale(scale, scale); 54 | ofSetColor(255); 55 | mesh.draw(); 56 | } 57 | void keyPressed(int key) { 58 | if(key == ' ') { 59 | setup(); 60 | } 61 | } 62 | }; 63 | 64 | int main() { 65 | ofSetupOpenGL(400, 400, OF_WINDOW); 66 | ofRunApp(new ofApp()); 67 | } 68 | -------------------------------------------------------------------------------- /example-3d/addons.make: -------------------------------------------------------------------------------- 1 | ofxAssignment 2 | -------------------------------------------------------------------------------- /example-3d/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "ofxAssignment.h" 3 | 4 | class ofApp : public ofBaseApp { 5 | public: 6 | ofEasyCam cam; 7 | ofxAssignment solver; 8 | vector initial, grid; 9 | void setup() { 10 | int side = 12; 11 | int n = side * side * side; 12 | 13 | // first, generate some data on a random walk modulo one 14 | initial.clear(); 15 | ofVec3f cur; 16 | ofSeedRandom(ofGetSystemTimeMicros()); 17 | for(int i = 0; i < n; i++) { 18 | cur += ofVec3f(ofRandomf(), ofRandomf(), ofRandomf()) * .01; 19 | cur.x = fmodf(cur.x, 1); 20 | cur.y = fmodf(cur.y, 1); 21 | cur.z = fmodf(cur.z, 1); 22 | initial.push_back(cur); 23 | } 24 | 25 | // then build the grid 26 | grid = makeGrid(side, side, side); 27 | 28 | // and finally, match the grid to the data 29 | auto start = ofGetElapsedTimeMillis(); 30 | grid = solver.match(initial, grid); 31 | auto stop = ofGetElapsedTimeMillis(); 32 | 33 | // 1728 points in 751ms 34 | // 8000 points in 64432ms 35 | cout << grid.size() << " points in " << (stop - start) << "ms" << endl; 36 | 37 | ofBackground(0); 38 | glPointSize(6); 39 | } 40 | void draw() { 41 | ofMesh mesh; 42 | mesh.setMode(OF_PRIMITIVE_POINTS); 43 | int n = initial.size(); 44 | float t = ofMap(cos(ofGetElapsedTimef()), -1, 1, 0, 1); 45 | ofSeedRandom(0); 46 | for(int i = 0; i < n; i++) { 47 | mesh.addVertex(grid[i] * t + initial[i] * (1 - t)); 48 | mesh.addColor(ofFloatColor(initial[i].x, initial[i].y, initial[i].z)); 49 | } 50 | ofSetColor(255); 51 | 52 | cam.begin(); 53 | float scale = ofGetWidth() / 2; 54 | ofRotateY(ofGetElapsedTimef() * 16.); 55 | ofTranslate(-scale / 2, -scale / 2, -scale / 2); 56 | ofScale(scale, scale, scale); 57 | mesh.draw(); 58 | cam.end(); 59 | } 60 | void keyPressed(int key) { 61 | if(key == ' ') { 62 | setup(); 63 | } 64 | } 65 | }; 66 | 67 | int main() { 68 | ofSetupOpenGL(400, 400, OF_WINDOW); 69 | ofRunApp(new ofApp()); 70 | } 71 | -------------------------------------------------------------------------------- /example-data/addons.make: -------------------------------------------------------------------------------- 1 | ofxAssignment 2 | -------------------------------------------------------------------------------- /example-data/bin/data/data.tsv: -------------------------------------------------------------------------------- 1 | 9.011495 3.616090 2 | 8.033435 11.638755 3 | 6.514205 2.521761 4 | 6.492563 2.866416 5 | 6.450499 3.612204 6 | 5.259153 4.665332 7 | 5.308672 4.631335 8 | 17.798515 -2.238952 9 | 17.715719 -2.326496 10 | 19.103389 -7.100080 11 | 13.371522 -2.042035 12 | 13.080010 -1.596981 13 | 12.770926 -2.375294 14 | 13.541799 -2.685721 15 | 12.488076 -3.790930 16 | 14.570128 -2.551934 17 | 13.610810 -3.499574 18 | 13.027637 -4.395542 19 | 13.261959 -4.837943 20 | 13.473688 -2.947276 21 | 13.306194 -8.199386 22 | 15.423563 -5.547187 23 | 15.737114 -6.243104 24 | 15.853228 -6.250903 25 | 15.656449 -5.293108 26 | 9.955263 13.480294 27 | 9.742415 12.481259 28 | 9.862449 12.582304 29 | 9.876563 13.514705 30 | 8.941590 12.060517 31 | 12.396847 14.747792 32 | 12.551498 14.357260 33 | 12.433240 14.540938 34 | 6.868189 6.376403 35 | 6.923732 6.317290 36 | 10.927688 16.031273 37 | 10.932877 16.059541 38 | 10.884401 16.085555 39 | 13.046320 11.720629 40 | 15.123714 11.096027 41 | 13.202848 12.781539 42 | 13.391367 11.307760 43 | 14.175648 11.944537 44 | 14.661592 11.760666 45 | 13.378533 11.204715 46 | 14.812814 9.992110 47 | 13.287357 12.788800 48 | 14.159423 12.912875 49 | 15.340081 10.445526 50 | 15.170624 8.145157 51 | 15.137577 8.138949 52 | 24.535661 -7.740772 53 | 9.915022 9.043835 54 | 10.058534 8.806367 55 | 11.974130 8.140298 56 | 11.242690 10.658348 57 | 11.296076 7.648981 58 | 10.202661 9.137857 59 | 10.153054 8.127648 60 | 11.288993 10.525132 61 | 11.402189 7.997545 62 | 12.609957 6.975608 63 | 12.493371 7.117629 64 | 11.245397 6.945817 65 | 11.273403 10.535698 66 | 9.200927 7.443186 67 | 12.151257 8.622027 68 | 12.545673 7.964065 69 | 12.139791 8.536061 70 | 4.505161 11.047375 71 | 7.471729 21.560658 72 | 6.219795 15.386279 73 | 7.151239 22.933836 74 | 7.259606 22.404024 75 | 7.287413 22.737058 76 | 6.767489 21.807864 77 | 8.695511 22.102689 78 | 8.121768 22.130821 79 | 6.095598 21.125203 80 | 6.559629 15.319019 81 | 16.938669 -4.348103 82 | 17.178336 -3.732710 83 | 16.155461 -3.387746 84 | 16.994330 -4.336446 85 | 17.838836 -6.031171 86 | 15.481160 -3.169049 87 | 16.113524 -3.337967 88 | 9.831683 -5.332870 89 | 10.224321 -4.642650 90 | 14.018278 -6.521745 91 | 10.376664 -4.289354 92 | 14.614057 -4.650570 93 | 11.106982 -3.397797 94 | 11.433608 -5.751584 95 | 11.539698 -2.742279 96 | 11.236861 -3.164143 97 | 11.205282 -5.557141 98 | 15.145479 -9.277328 99 | 14.411644 -10.014554 100 | 15.560738 -9.525317 101 | 15.748306 -9.819516 102 | 24.946874 -6.847893 103 | 18.536602 6.385290 104 | 17.977868 4.607659 105 | 24.881898 3.297890 106 | 22.253081 9.277290 107 | 23.840036 3.966226 108 | 2.156332 9.393618 109 | 2.755981 8.386654 110 | 3.422493 7.865595 111 | 5.963311 9.419022 112 | 6.920637 9.566044 113 | 2.944264 11.616719 114 | 6.157592 12.517248 115 | 6.300134 12.461617 116 | 5.670709 9.321603 117 | 4.602671 10.416743 118 | 2.454574 10.217987 119 | 3.185558 13.923725 120 | 3.693540 13.507508 121 | 4.205160 13.625489 122 | 3.197127 13.952466 123 | 3.870655 15.132998 124 | 4.031101 15.083753 125 | 4.148265 15.091905 126 | 3.120856 12.066620 127 | 4.650429 11.710433 128 | 16.867646 -10.543296 129 | 16.641048 -10.491766 130 | 17.895752 -10.504566 131 | 18.216220 -10.677617 132 | 17.533791 -8.718234 133 | 17.632093 -9.302041 134 | 17.219451 -7.684555 135 | 17.736354 -9.280723 136 | 16.906939 -8.206028 137 | 14.849595 -8.060444 138 | 14.971400 -8.539168 139 | 18.244942 -6.916455 140 | 13.188555 -10.097390 141 | 12.911431 -9.707634 142 | 13.716080 -9.917647 143 | 13.208669 -9.633904 144 | 14.611458 -10.813339 145 | 17.070987 -11.217161 146 | 14.996775 -12.464888 147 | 15.469226 -11.591285 148 | 5.758185 1.856159 149 | 5.945362 1.574884 150 | 5.373982 2.674374 151 | 18.912957 3.154710 152 | 35.364899 6.471753 153 | 34.510591 -2.610242 154 | 36.074230 -4.748861 155 | 34.591360 -3.631035 156 | 35.291661 -4.082081 157 | 43.457296 1.737740 158 | 34.368399 -2.424914 159 | 35.788555 6.472473 160 | 39.884198 7.559393 161 | 39.302174 -1.467253 162 | 40.490780 5.043124 163 | 40.844936 5.031305 164 | 39.834818 6.213502 165 | 42.224690 5.614512 166 | 38.831506 5.956329 167 | 41.459894 5.432074 168 | 41.515490 5.468499 169 | 39.846790 7.018674 170 | 39.883941 -0.730249 171 | 40.356220 -1.989200 172 | 36.577160 8.689747 173 | 36.922956 8.651576 174 | 37.043607 7.875667 175 | 33.384690 3.450833 176 | 37.923127 -3.493894 177 | 39.809541 -0.408821 178 | 40.441893 -1.951510 179 | 40.872963 8.129956 180 | 38.130100 9.255333 181 | 38.205170 9.115127 182 | 41.899740 -4.656487 183 | 38.679100 -7.049485 184 | 40.709387 -4.094210 185 | 39.485242 -6.362436 186 | 37.758079 -6.853791 187 | 37.708071 -6.849775 188 | 36.540721 -7.285663 189 | 40.581451 -5.756501 190 | 40.555885 -6.069216 191 | 38.007248 -4.659973 192 | 40.645018 -6.361635 193 | 37.658618 -5.980237 194 | 37.167610 -7.170451 195 | 37.475898 -4.422471 196 | 37.396582 10.539309 197 | 39.329417 -4.705540 198 | 39.755523 -4.067364 199 | 39.680930 -4.355910 200 | 38.613616 -5.106196 201 | 36.521732 -3.509446 202 | 36.568273 -7.386541 203 | 39.258092 -6.133317 204 | 36.988488 -5.430086 205 | 35.544861 -4.134208 206 | 39.812644 1.449086 207 | 42.314039 -1.198993 208 | 40.804792 2.162290 209 | 40.064544 2.504068 210 | 41.352586 7.564234 211 | 42.705563 5.836872 212 | 40.462771 7.701016 213 | 42.407757 2.780557 214 | 41.492406 1.643457 215 | 40.329956 1.352488 216 | 42.773593 3.042300 217 | 42.331311 0.639005 218 | 43.095813 2.874261 219 | 43.101682 2.478052 220 | 42.540678 1.054252 221 | 42.265951 0.689481 222 | 42.454357 -1.531722 223 | 36.237367 -0.698416 224 | 36.565931 2.036145 225 | 36.710308 1.875540 226 | 33.935700 4.598939 227 | 38.919088 -2.600331 228 | 36.394557 4.848715 229 | 37.509739 -1.888635 230 | 37.124506 -2.617419 231 | 34.692860 1.345851 232 | 34.898779 1.566872 233 | 35.100770 1.721528 234 | 39.922106 -3.541663 235 | 37.920089 5.311979 236 | 33.769418 4.212106 237 | 37.663955 5.892532 238 | 36.764627 6.184613 239 | 38.656422 3.973455 240 | 38.522155 3.539598 241 | 38.375959 4.139350 242 | 38.589991 4.167691 243 | 38.947919 9.654739 244 | 39.066189 9.581865 245 | 37.920005 0.514700 246 | 37.707120 10.571274 247 | 38.880874 8.590210 248 | 38.262249 2.317236 249 | 32.238956 2.395319 250 | 32.687666 2.322832 251 | 32.447414 2.447519 252 | 41.076264 9.741453 253 | 35.041827 -6.209737 254 | 36.476392 7.471340 255 | 38.661660 10.877957 256 | 38.065857 1.311759 257 | 38.299594 0.663539 258 | 36.017375 -0.635301 259 | 34.958831 -0.395264 260 | 33.446450 -1.297816 261 | 33.771369 -0.737549 262 | 33.098202 -0.071224 263 | 34.812481 -6.292192 264 | 35.417146 3.487996 265 | 35.486533 3.527783 266 | 42.898384 -4.183503 267 | 42.757664 -4.044507 268 | 42.677633 -3.664928 269 | 35.662161 8.854851 270 | 29.063387 2.776036 271 | 29.513425 2.979215 272 | 28.098755 2.438357 273 | 28.076401 2.794168 274 | 28.865696 1.900631 275 | 27.754454 1.861566 276 | 27.018228 0.643388 277 | 26.969833 0.644388 278 | 26.971418 2.934084 279 | 26.927560 2.954064 280 | 29.725340 3.359149 281 | 26.928738 3.057059 282 | 29.251660 7.009604 283 | 28.958156 7.136145 284 | 31.942783 -1.764000 285 | 30.758325 6.640910 286 | 29.482804 6.825951 287 | 27.770251 5.846394 288 | 28.293483 6.160280 289 | 26.370719 6.762029 290 | 26.394587 6.920921 291 | 26.627149 6.723115 292 | 27.540981 5.513116 293 | 28.357829 7.360260 294 | 26.085075 6.355215 295 | 27.002903 9.653676 296 | 26.680094 9.974525 297 | 30.048426 4.271793 298 | 26.486846 10.172227 299 | 21.139998 7.028585 300 | 21.128095 7.163689 301 | 5.286110 19.124790 302 | 3.362971 19.603482 303 | 5.000329 18.972951 304 | 4.823267 19.700698 305 | 3.971181 19.652668 306 | 4.826484 18.273553 307 | 4.281641 18.238474 308 | 4.427638 19.759877 309 | 2.656011 20.719441 310 | 2.168418 20.567608 311 | 5.842429 19.971813 312 | 7.181911 18.964438 313 | 7.075059 18.879749 314 | 8.374362 19.269050 315 | 6.218137 17.764222 316 | 8.237355 19.205975 317 | 3.896233 21.270013 318 | 4.083866 21.211340 319 | 3.589973 22.240911 320 | 4.647220 23.260466 321 | 4.610759 23.234048 322 | 2.235419 23.970655 323 | 2.148442 23.351285 324 | 1.883233 24.172767 325 | 1.647285 22.780397 326 | 1.614426 22.875327 327 | 2.347377 22.990331 328 | 4.414520 9.172478 329 | 3.754542 8.531540 330 | 4.626823 9.560405 331 | 24.344310 2.448702 332 | 24.342615 2.395850 333 | 31.162650 -2.336623 334 | 30.189089 -2.935443 335 | 18.726771 6.411418 336 | 22.527380 6.775451 337 | 22.227572 6.565057 338 | 19.039464 4.641163 339 | 30.422864 -2.821677 340 | 23.482356 -3.929734 341 | 22.220740 -2.544448 342 | 23.796727 0.361872 343 | 23.841452 0.216736 344 | 23.902475 -0.289214 345 | 19.830036 1.686002 346 | 24.424509 -4.663045 347 | 24.607358 -4.935668 348 | 25.141289 -4.682783 349 | 25.739476 -2.618111 350 | 25.506919 -2.424728 351 | 25.113925 -2.184067 352 | 23.421763 -2.657417 353 | 23.199344 -2.589645 354 | 23.260716 -2.618967 355 | 26.415008 -4.064721 356 | 26.371333 -3.372832 357 | 20.548016 4.481488 358 | 20.159799 4.417734 359 | 21.173706 4.574780 360 | 21.201248 4.528589 361 | 19.203092 4.036810 362 | 22.148672 4.425285 363 | 22.245242 4.501107 364 | 17.139296 7.473623 365 | 21.017093 10.302939 366 | 24.794831 13.135282 367 | 25.266332 12.460224 368 | 25.037454 12.588965 369 | 23.963132 12.183243 370 | 24.507596 12.351496 371 | 22.315579 12.675081 372 | 21.894411 12.948737 373 | 22.327431 14.059470 374 | 22.190624 13.717283 375 | 22.694342 13.028093 376 | 23.096890 12.933216 377 | 21.244614 13.369751 378 | 21.336216 11.398260 379 | 22.288588 11.932816 380 | 23.225863 11.596997 381 | 21.614562 11.593467 382 | 22.996426 11.876608 383 | 22.262627 11.352969 384 | 23.118445 9.618083 385 | 23.064713 9.799712 386 | 24.999547 -6.748557 387 | 24.886402 -6.835019 388 | 27.441303 11.980936 389 | 27.427871 11.981667 390 | 8.511797 3.499026 391 | 8.823336 7.199009 392 | 8.470556 3.153676 393 | 3.785927 6.723044 394 | 2.578986 8.260637 395 | 7.576447 3.247959 396 | 8.255786 3.622406 397 | 2.740489 7.465238 398 | 4.599001 6.911673 399 | -20.335948 -15.681695 400 | -15.376059 -3.739879 401 | -16.657519 -4.969869 402 | -26.323008 -12.539066 403 | -26.731308 -14.745290 404 | -1.449520 -17.534825 405 | -2.894960 -17.073609 406 | -3.628171 -14.750436 407 | -3.295420 -8.929199 408 | -8.390019 -25.048501 409 | -3.266168 -21.277164 410 | -38.799655 -5.090913 411 | -2.085855 25.182272 412 | -13.920115 0.295298 413 | -13.135772 -17.678836 414 | -21.743639 -7.382408 415 | -19.089177 0.563882 416 | -15.222090 17.708249 417 | -6.650224 -4.071278 418 | -5.614229 -11.622697 419 | -23.339128 0.144597 420 | -20.056700 5.274457 421 | -26.198565 -14.829159 422 | -3.753282 -3.479745 423 | -24.394729 10.765894 424 | -18.241660 16.137915 425 | -18.197029 16.237021 426 | 1.206655 -10.156775 427 | -39.107140 -4.679255 428 | -11.793613 -17.875209 429 | -0.456613 -25.782319 430 | -27.699336 14.023101 431 | -25.783238 13.862175 432 | -12.148875 -11.543303 433 | -24.316817 -12.930731 434 | -11.546370 3.367926 435 | -15.815862 0.782806 436 | -30.794144 9.221504 437 | -6.673130 -26.803670 438 | 3.237853 -14.166603 439 | -14.890529 8.056633 440 | -19.527867 -9.374970 441 | -19.817537 11.574940 442 | -17.813594 12.430440 443 | -1.165651 -8.909550 444 | -14.264716 0.486424 445 | -0.278668 -28.505998 446 | -11.029386 1.840676 447 | -22.252879 1.715584 448 | -28.711436 -5.354225 449 | 3.519683 -5.028025 450 | 2.169468 -15.848679 451 | 0.400036 -22.040120 452 | -20.355176 -2.271879 453 | -11.690108 -2.312879 454 | -31.950808 1.946837 455 | -18.435932 18.487678 456 | -20.855039 11.133771 457 | -21.841518 -10.258376 458 | -17.006432 -1.727203 459 | -0.539296 -5.615336 460 | -10.502186 1.629781 461 | 3.435077 -14.648862 462 | -17.837483 -8.587108 463 | -10.023243 -9.041233 464 | -12.446999 -17.202010 465 | -20.396968 -0.865102 466 | -19.601619 -7.360640 467 | -8.256448 -20.914707 468 | -15.934898 19.371431 469 | -7.312423 -26.643494 470 | -9.088991 10.789908 471 | -17.259429 6.718039 472 | -3.937563 -20.005895 473 | -1.279407 -15.049495 474 | -24.288661 -1.978035 475 | -13.423439 -3.037179 476 | -38.096538 -0.478318 477 | -1.595552 -1.518902 478 | -24.411467 -3.869061 479 | -28.185516 3.117241 480 | -6.234241 -28.789523 481 | -36.181024 3.022427 482 | -31.319712 -3.476992 483 | -31.589051 -3.972555 484 | -0.745912 -9.957338 485 | 2.667163 -19.737436 486 | -31.902791 -4.136082 487 | -25.716900 -15.962380 488 | -34.700910 -4.520935 489 | -26.592278 -1.201666 490 | 3.379856 -7.588222 491 | -17.704556 -8.145757 492 | -13.142940 -24.703454 493 | -28.663703 2.068874 494 | -30.643066 2.027722 495 | -19.942038 -13.343467 496 | -31.226543 2.808491 497 | -11.335429 -5.237578 498 | -0.655798 -9.482700 499 | -16.442311 16.866875 500 | -11.727781 7.985207 501 | 5.718230 -12.420309 502 | -15.028304 -3.853942 503 | -21.702212 16.477521 504 | -17.324767 9.349564 505 | -14.611301 11.782630 506 | -15.670888 9.849630 507 | -3.692857 -3.395120 508 | -28.892311 -1.303323 509 | -34.451097 -6.450384 510 | -16.781706 19.138667 511 | 0.937827 -17.720865 512 | -6.140648 -27.589120 513 | -24.313589 -2.070549 514 | -24.328525 -14.138626 515 | -21.673806 15.479916 516 | -7.854971 3.079856 517 | -12.238710 -11.446739 518 | -0.453896 -19.414886 519 | -15.850426 -7.338318 520 | -28.267355 3.043503 521 | -12.522697 -11.218017 522 | -10.023217 11.451384 523 | -28.305300 15.955939 524 | -22.179413 -9.190037 525 | -17.896598 -8.591607 526 | 2.361650 -14.258786 527 | -31.870380 0.498249 528 | -33.781124 -1.566261 529 | -36.762930 2.040793 530 | -13.244722 2.282242 531 | -37.588705 -5.069718 532 | -37.751785 -4.222650 533 | -15.107414 4.921242 534 | -12.696559 -4.847273 535 | -32.283519 5.059523 536 | -6.325113 -29.740247 537 | 1.322497 -17.389491 538 | 31.699180 2.185360 539 | -2.370624 -10.703179 540 | -24.774468 6.385053 541 | 0.084140 -18.961830 542 | -22.238043 -15.801615 543 | -22.420209 -15.740481 544 | -24.418456 10.733728 545 | -9.076416 10.297716 546 | -31.327666 -8.405704 547 | -26.836507 -14.623280 548 | -7.088369 -21.342389 549 | -33.233245 0.900379 550 | -22.618827 2.572938 551 | -15.585597 9.588693 552 | -21.833399 6.399196 553 | -10.375519 -2.867419 554 | -31.474539 0.966581 555 | 0.893523 -18.546220 556 | -4.672930 -25.090101 557 | -16.373285 -13.804571 558 | -6.572652 -8.116887 559 | -23.912735 -12.243835 560 | -8.998017 -12.482367 561 | -26.629183 12.660704 562 | -3.270324 -23.809381 563 | -0.337978 -7.674278 564 | -23.204129 -0.188081 565 | -13.567717 -10.166933 566 | -6.801762 -20.946762 567 | -24.019626 -14.061516 568 | -9.889951 9.672751 569 | -14.346007 -3.872982 570 | -5.398912 -23.929076 571 | -18.975804 -5.293550 572 | -37.075646 3.169081 573 | -17.883934 12.381377 574 | -4.252527 -28.185744 575 | -28.414565 15.701534 576 | -3.923807 -26.691927 577 | -0.795744 -14.027914 578 | -19.999472 -13.308929 579 | -10.812649 -0.793069 580 | -28.154880 -12.198222 581 | 2.815583 -8.379241 582 | -6.709612 -27.716126 583 | -16.217821 19.278834 584 | -20.834161 -12.121666 585 | -21.216686 -2.085488 586 | -20.949964 6.412816 587 | -4.027253 -21.095738 588 | -23.848294 -5.320695 589 | -11.386101 -13.574973 590 | -27.130837 -7.807659 591 | -35.031443 -4.404428 592 | -15.742915 0.618661 593 | -32.781851 -3.816523 594 | -24.392127 -10.895114 595 | -22.460105 -11.998286 596 | -2.091538 -24.036124 597 | -23.714907 -5.494738 598 | -21.270180 -5.475979 599 | -33.492899 0.678078 600 | -2.064111 25.152187 601 | -26.916174 -1.724383 602 | -11.586364 -0.962963 603 | -6.786149 -4.620784 604 | 1.503201 -25.159528 605 | -15.846998 7.522648 606 | -34.042985 -4.240773 607 | -28.713537 -7.435919 608 | -8.604971 20.892965 609 | -14.960857 -0.989572 610 | -5.473374 -25.570396 611 | -15.183895 -2.110928 612 | -24.254204 5.082267 613 | -0.202254 -27.251295 614 | -33.201096 -5.929731 615 | -13.264594 -1.003532 616 | -13.809875 2.838772 617 | -26.658574 -1.309808 618 | -18.285715 -3.153895 619 | -12.053174 9.660210 620 | -17.244127 -11.682653 621 | -35.014775 -2.711170 622 | -1.834835 -25.397496 623 | -29.380053 -4.528965 624 | -23.054821 -1.257896 625 | -18.707815 18.445967 626 | 1.130530 -18.885328 627 | -20.796641 3.795418 628 | -7.976568 -26.353259 629 | 1.067686 -17.319272 630 | -21.745275 6.111883 631 | -22.136699 16.231846 632 | -20.408898 6.522120 633 | -31.643447 -5.557207 634 | -28.450397 -4.156000 635 | -2.382948 -23.033144 636 | -38.863611 -4.059812 637 | -19.478965 0.575184 638 | -13.513330 -17.823085 639 | -11.347086 1.837858 640 | -11.339606 1.988817 641 | -0.345923 -4.677691 642 | -21.743473 -14.937290 643 | -20.993037 -15.658235 644 | -14.989699 -6.019501 645 | -20.800865 3.167584 646 | -6.607333 -8.161523 647 | -0.320502 -4.331972 648 | -14.667366 8.434166 649 | -32.346357 3.645779 650 | 4.945723 -10.349875 651 | -27.262678 -8.336042 652 | -31.907624 4.780779 653 | -19.781197 -7.665825 654 | -11.689621 -17.308145 655 | -7.540781 -25.072221 656 | -12.016778 0.909198 657 | -7.492680 -25.684813 658 | -4.179445 -18.448431 659 | -12.071238 -4.783742 660 | -12.050728 11.995198 661 | -6.875033 -23.365245 662 | -4.137021 -26.489588 663 | -32.939515 -4.106103 664 | -1.425666 -9.435656 665 | -34.105440 -1.135485 666 | -1.686237 -28.948812 667 | -12.504222 11.288845 668 | -16.722239 -5.010831 669 | -2.294889 -10.468850 670 | -13.653172 -10.596225 671 | -1.822533 -28.977624 672 | -0.059382 -28.997769 673 | 2.104355 -11.665910 674 | -34.114921 -6.111514 675 | -27.593712 1.507052 676 | -6.374579 -24.181499 677 | 34.418101 6.288119 678 | -26.370157 -3.339555 679 | -18.238909 -5.813914 680 | -25.889708 -0.917501 681 | -19.671030 8.387853 682 | -34.987686 -2.723422 683 | -1.871608 -7.181904 684 | -24.200820 -12.761913 685 | -24.163923 -10.744147 686 | -37.795503 -5.599665 687 | -17.943916 3.979912 688 | -27.868873 -11.535421 689 | -33.104815 -2.663978 690 | -11.721624 -1.032680 691 | 1.591776 -25.120799 692 | -18.877456 -5.308946 693 | -22.702028 3.057083 694 | -1.360526 -15.019571 695 | 0.818484 -16.139622 696 | -28.250534 -1.337943 697 | -22.838300 -3.245850 698 | -13.304467 -0.982664 699 | -1.520191 -9.662475 700 | -22.987808 -11.800509 701 | -28.038821 6.264572 702 | -5.856126 -11.437291 703 | -6.662109 -4.470213 704 | -9.061188 -14.838025 705 | -37.815966 2.203756 706 | -7.668823 -21.793671 707 | -1.021591 -12.135918 708 | -36.839141 2.364848 709 | -1.772585 -7.023112 710 | -20.840583 0.861874 711 | -23.963028 1.039279 712 | -19.864139 6.870001 713 | -14.257211 7.628318 714 | -31.912955 -1.454158 715 | -27.594102 -14.541090 716 | -19.458273 -9.305196 717 | 4.102308 -7.436789 718 | -5.854883 -26.442926 719 | 1.326449 -14.476559 720 | -17.961480 8.273585 721 | -20.514230 8.165473 722 | -13.438408 -8.527035 723 | -30.338199 14.410367 724 | -4.948792 1.763992 725 | 2.963344 -18.085187 726 | -16.694925 10.935520 727 | -24.958246 -4.399651 728 | -3.297457 -12.064472 729 | -17.111108 1.527017 730 | -30.948213 3.525673 731 | -1.301396 -24.189989 732 | -24.261510 -6.832275 733 | -30.206049 -4.812623 734 | -6.764266 -7.876418 735 | -8.160337 -25.036219 736 | -13.562526 -3.077021 737 | -30.861699 14.166813 738 | -20.015060 11.260767 739 | -16.168987 12.564179 740 | -14.439541 15.289123 741 | -25.790036 -6.380622 742 | -24.680683 6.202516 743 | -31.946416 -1.508348 744 | -4.329760 -6.933149 745 | -4.201437 -18.454450 746 | -30.783312 -6.641704 747 | -23.149419 8.136814 748 | -24.131202 11.381438 749 | -20.073487 0.641754 750 | -22.853539 -0.957397 751 | -13.377922 -8.873805 752 | -5.062458 -28.100703 753 | -29.067778 14.526959 754 | -31.514517 -9.540925 755 | -32.161534 -4.863414 756 | -4.464774 -13.703448 757 | -11.855558 -18.014299 758 | -7.076972 -23.730794 759 | -8.351489 -7.200454 760 | -29.504347 -4.861194 761 | -32.584203 4.485351 762 | -34.403345 -5.021786 763 | -15.828170 17.242346 764 | -21.980505 -6.677348 765 | -21.795814 -7.417302 766 | -9.030105 -12.422150 767 | -8.056215 7.801326 768 | -23.550227 0.775478 769 | -26.342207 14.494289 770 | -25.354753 1.165320 771 | -22.475618 17.021361 772 | -29.423885 -0.763482 773 | -21.381304 -2.088496 774 | -17.719766 7.260123 775 | -22.018725 16.679578 776 | -12.327114 0.339461 777 | -24.820802 -13.635346 778 | -21.287295 -4.990455 779 | -33.019926 8.649633 780 | -8.588017 -23.589446 781 | 2.887793 -18.335176 782 | -15.770597 -20.636735 783 | -34.109658 -1.142851 784 | -26.421034 -3.359619 785 | -24.180295 -3.709495 786 | -17.827370 -0.750139 787 | -29.577968 -7.308154 788 | -17.631242 -8.941199 789 | -20.897142 17.119287 790 | -15.273476 -14.272385 791 | -10.965168 -13.997927 792 | -10.504697 -14.343406 793 | -9.214323 -10.169055 794 | -11.554782 3.669591 795 | -14.752050 -11.993365 796 | -6.386168 -16.043034 797 | -14.810356 -5.971764 798 | -12.732405 -7.500363 799 | -25.555221 1.247656 800 | -15.083115 -14.332776 801 | -35.312616 4.186894 802 | 2.111759 3.783751 803 | 0.489707 -21.879356 804 | -4.095317 -23.991128 805 | -29.949205 8.018548 806 | -26.146026 14.707456 807 | -11.569658 -5.087684 808 | -4.619012 -13.748272 809 | -7.846406 3.074435 810 | -11.599001 12.180308 811 | -34.496463 -7.607917 812 | -31.487088 -9.285785 813 | -3.494340 -17.545036 814 | -11.722430 8.479530 815 | 1.263166 -19.890548 816 | 7.532607 23.436271 817 | -8.078925 -0.990509 818 | -5.518141 -28.102101 819 | -30.769650 -7.034862 820 | -27.207280 -9.907945 821 | -6.376609 -21.293342 822 | 1.088047 -14.429150 823 | -21.913554 -16.427879 824 | -19.068224 -3.318551 825 | -13.256333 -3.335293 826 | 4.866986 -10.230813 827 | -38.037591 -4.210090 828 | -9.807190 7.423748 829 | -12.848517 9.524155 830 | -8.291527 -22.155660 831 | -9.412302 -25.176122 832 | -13.353028 -9.640687 833 | -1.538526 -10.506773 834 | -0.765053 -17.552620 835 | -16.941372 -2.230179 836 | -0.612506 -5.818210 837 | -26.288211 8.607798 838 | -26.289727 8.621267 839 | -20.361162 6.061971 840 | 1.359815 -14.045070 841 | -10.078799 -8.969623 842 | -15.095468 -2.379543 843 | -12.419577 2.243065 844 | -7.128432 -5.224065 845 | -29.198049 -1.992068 846 | -23.855821 -3.275183 847 | -17.257568 -11.684379 848 | -3.857274 -20.805481 849 | -31.675105 -4.028563 850 | -15.747385 10.227318 851 | 44.018701 -4.963350 852 | -34.122341 -0.370478 853 | -29.222435 14.669119 854 | 1.874936 -9.916231 855 | -27.458827 -10.598214 856 | -18.121008 6.613832 857 | -2.122185 -23.662418 858 | -4.153285 -9.213008 859 | 1.221481 -8.926936 860 | -30.428517 5.234079 861 | -17.763873 18.667392 862 | -31.853090 7.007531 863 | -16.896433 5.738411 864 | -2.740492 -6.750936 865 | -5.203402 -24.971402 866 | -17.379034 19.440634 867 | -2.254921 -24.470555 868 | -5.969379 -24.089495 869 | -9.989837 13.153112 870 | -17.018182 -2.830712 871 | -0.449765 -27.810925 872 | 2.602012 -19.721632 873 | -22.433715 -8.930580 874 | -1.949549 -8.185597 875 | -8.327263 -22.309816 876 | -24.275338 -14.253036 877 | -30.803509 9.281358 878 | -5.045346 -5.866495 879 | -34.459128 -7.743949 880 | -6.479187 -10.940974 881 | 0.005966 -29.035976 882 | -28.010157 -12.048299 883 | -28.040245 -7.507755 884 | -16.517872 11.808527 885 | -2.193875 -9.035132 886 | -12.439338 -3.545977 887 | -35.459409 3.789038 888 | -15.821351 -4.466664 889 | 1.047201 -13.788436 890 | -25.691383 -15.964596 891 | -26.069900 14.525377 892 | -9.782277 8.994684 893 | -39.126684 -5.285098 894 | -20.993504 1.064094 895 | -30.710888 1.980969 896 | -2.586328 -17.420743 897 | -30.325835 8.189072 898 | -32.115343 6.485792 899 | -19.302563 10.061382 900 | -16.961012 10.440584 901 | -3.668973 -12.937394 902 | -17.355170 10.742350 903 | -24.401458 -10.018723 904 | -10.741774 -2.827807 905 | -15.187973 -13.401338 906 | -15.110507 -13.313484 907 | -17.253487 -1.595213 908 | -19.402984 11.998943 909 | -2.743809 -17.192233 910 | -9.811306 10.029732 911 | -11.925238 9.548980 912 | -12.622591 -3.901869 913 | 4.047929 -7.410639 914 | 2.945647 -16.694707 915 | 2.885452 -18.772731 916 | 1.958962 -11.331968 917 | -35.174309 -0.999940 918 | -23.616086 4.035051 919 | -25.664675 4.117437 920 | -14.449637 -20.954635 921 | -14.312599 -21.035547 922 | -23.462664 3.739171 923 | -25.650472 4.147763 924 | -10.359466 14.116962 925 | -9.731522 16.511570 926 | -11.312050 12.822986 927 | -9.941214 11.507548 928 | -11.627515 14.636864 929 | -11.987700 14.447803 930 | -19.120327 4.839837 931 | -12.097911 17.096570 932 | -12.177676 17.722447 933 | -12.482258 18.187506 934 | -11.002933 17.971293 935 | -11.030260 17.955029 936 | -10.335670 15.367450 937 | -7.378695 16.178889 938 | -7.818712 15.684760 939 | -7.639143 15.914937 940 | -6.811649 17.746914 941 | -8.152786 18.894279 942 | -8.002604 18.846891 943 | -8.243059 18.944229 944 | -6.692985 17.824512 945 | -2.532933 20.874918 946 | -6.527233 18.561427 947 | -2.155369 20.981212 948 | -1.832292 13.817628 949 | -5.873568 19.181628 950 | -4.364402 19.081039 951 | -5.666428 20.214529 952 | -5.744429 20.108791 953 | -5.024076 19.042898 954 | -4.998785 20.823440 955 | -5.282209 20.896988 956 | -6.534014 20.265237 957 | -4.353689 20.435659 958 | -4.005033 19.152811 959 | 2.578610 -23.944234 960 | -9.769652 14.285556 961 | -12.189794 14.205142 962 | -12.980760 15.578978 963 | -10.475795 15.412728 964 | -11.227260 16.340558 965 | -10.906558 16.000301 966 | -10.088086 16.843279 967 | -18.987669 12.275536 968 | -14.448738 12.116365 969 | -14.518450 11.767173 970 | -13.124583 13.400559 971 | 4.632672 -12.938288 972 | -5.740576 0.362503 973 | 5.366238 -12.991953 974 | 3.339670 7.610155 975 | 6.088278 -14.167425 976 | 4.263855 -15.051533 977 | 4.647302 -14.506612 978 | 4.619489 -15.625791 979 | 4.568507 -15.159850 980 | 5.067703 -13.440291 981 | 6.062648 -13.901850 982 | -27.627775 13.823013 983 | -10.403084 -0.835156 984 | 2.248248 3.876171 985 | 4.881351 -8.670222 986 | 1.038442 20.341793 987 | -0.267373 20.638358 988 | -4.805604 15.834826 989 | -2.301097 17.591756 990 | -2.922349 18.969250 991 | -2.316703 17.661415 992 | -0.690491 12.812611 993 | -1.779239 13.926743 994 | -1.131200 12.792250 995 | -0.365829 13.494001 996 | -0.553349 13.494454 997 | -1.233036 12.959038 998 | -2.133197 13.888492 999 | -4.777879 15.854287 1000 | -28.046450 6.269014 1001 | -------------------------------------------------------------------------------- /example-data/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | #include "ofxAssignment.h" 3 | 4 | class ofApp : public ofBaseApp { 5 | public: 6 | ofxAssignment solver; 7 | vector> data, grid; 8 | void setup() { 9 | // first, load the data 10 | // this technique is useful for higher-dimensional matching 11 | data.clear(); 12 | ofBuffer buffer = ofBufferFromFile("data.tsv"); 13 | for(auto& line : buffer.getLines()) { 14 | vector chunks = ofSplitString(line, "\t"); 15 | if(chunks.size() == 2) { 16 | data.push_back(vector{ofToFloat(chunks[0]), ofToFloat(chunks[1])}); 17 | } 18 | } 19 | 20 | // then build the grid 21 | grid.clear(); 22 | for(const ofVec2f& point : makeGrid(120, 119)) { 23 | grid.push_back(vector{point.x, point.y}); 24 | } 25 | 26 | // resize the data if it's too much 27 | if(data.size() > grid.size()) { 28 | data.resize(grid.size()); 29 | } 30 | 31 | // and finally, match the grid to the data 32 | auto start = ofGetElapsedTimeMillis(); 33 | grid = solver.match(data, grid); 34 | auto stop = ofGetElapsedTimeMillis(); 35 | 36 | // 1000 points in 497ms 37 | cout << grid.size() << " points in " << (stop - start) << "ms" << endl; 38 | 39 | // write to output 40 | ofFile out("out.tsv", ofFile::WriteOnly); 41 | for(auto& point : grid) { 42 | out << point[0] << "\t" << point[1] << endl; 43 | } 44 | out.close(); 45 | 46 | ofBackground(0); 47 | glPointSize(6); 48 | } 49 | void draw() { 50 | ofMesh mesh; 51 | mesh.setMode(OF_PRIMITIVE_POINTS); 52 | int n = data.size(); 53 | float t = ofMap(cos(ofGetElapsedTimef()), -1, 1, 0, 1); 54 | ofSeedRandom(0); 55 | for(int i = 0; i < n; i++) { 56 | mesh.addVertex(ofVec2f(data[i][0] * t + grid[i][0] * (1 - t), 57 | data[i][1] * t + grid[i][1] * (1 - t))); 58 | mesh.addColor(ofFloatColor(1, data[i][0], data[i][1])); 59 | } 60 | float padding = 128; 61 | float scale = ofGetWidth() - 2 * padding; 62 | ofTranslate(padding, padding); 63 | ofScale(scale, scale); 64 | ofSetColor(255); 65 | mesh.draw(); 66 | } 67 | void keyPressed(int key) { 68 | if(key == ' ') { 69 | setup(); 70 | } 71 | } 72 | }; 73 | 74 | int main() { 75 | ofSetupOpenGL(400, 400, OF_WINDOW); 76 | ofRunApp(new ofApp()); 77 | } 78 | -------------------------------------------------------------------------------- /example-mosaic/addons.make: -------------------------------------------------------------------------------- 1 | ofxAssignment 2 | -------------------------------------------------------------------------------- /example-mosaic/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ofMain.h" 2 | 3 | ofColor getAverage(const ofPixels& pix, int x, int y, int w, int h) { 4 | float r = 0, g = 0, b = 0; 5 | for(int j = y; j < y + h; j++) { 6 | for(int i = x; i < x + w; i++) { 7 | const ofColor& cur = pix.getColor(i, j); 8 | r += cur.r; 9 | g += cur.g; 10 | b += cur.b; 11 | } 12 | } 13 | float n = w * h; 14 | return ofColor(r / n, g / n, b / n); 15 | } 16 | 17 | class Tile : public ofVec2f { 18 | public: 19 | int side; 20 | float brightness, hue; 21 | ofColor average; 22 | vector grid; 23 | Tile(int x, int y, int side, const vector& grid) 24 | :ofVec2f(x, y) 25 | ,side(side) 26 | ,grid(grid) { 27 | } 28 | static vector buildTiles(const ofPixels& pix, int side) { 29 | // we could do this with resizing but OF doesn't have a good downsampling method 30 | float third = side / 3.; 31 | int w = pix.getWidth(), h = pix.getHeight(); 32 | int nx = w / side, ny = h / side; 33 | vector tiles; 34 | for(int y = 0; y < h; y+=side) { 35 | for(int x = 0; x < w; x+=side) { 36 | vector grid; 37 | for(int ky = 0; ky < 3; ky++) { 38 | for(int kx = 0; kx < 3; kx++) { 39 | grid.push_back(getAverage(pix, x+kx*third, y+ky*third, third, third)); 40 | } 41 | } 42 | tiles.emplace_back(x, y, side, grid); 43 | } 44 | } 45 | return tiles; 46 | } 47 | }; 48 | 49 | float sqdistance(const ofColor& c1, const ofColor& c2) { 50 | long rmean = ((long) c1.r + (long) c2.r) / 2; 51 | long r = (long) c1.r - (long) c2.r; 52 | long g = (long) c1.g - (long) c2.g; 53 | long b = (long) c1.b - (long) c2.b; 54 | return ((((512 + rmean)*r*r)>>8) + 4*g*g + (((767-rmean)*b*b)>>8)); 55 | } 56 | 57 | #include "ofxAssignment.h" 58 | 59 | class ofApp : public ofBaseApp { 60 | public: 61 | ofVideoGrabber video; 62 | ofImage leftImage, rightImage; 63 | vector leftTiles, rightTiles; 64 | ofxAssignment solver; 65 | int side = 20; 66 | void setup() { 67 | // ofSetFrameRate(5); 68 | video.initGrabber(1280, 720); 69 | } 70 | void update() { 71 | video.update(); 72 | if(video.isFrameNew()) { 73 | int w = video.getWidth(); 74 | int h = video.getHeight(); 75 | ofPixels& pix = video.getPixels(); 76 | leftImage.allocate(w / 2, h, OF_IMAGE_COLOR); 77 | rightImage.allocate(w / 2, h, OF_IMAGE_COLOR); 78 | pix.cropTo(leftImage.getPixels(), 0, 0, w / 2, h); 79 | pix.cropTo(rightImage.getPixels(), w / 2, 0, w / 2, h); 80 | leftImage.update(); 81 | rightImage.update(); 82 | leftTiles = Tile::buildTiles(leftImage, side); 83 | rightTiles = Tile::buildTiles(rightImage, side); 84 | 85 | int n = leftTiles.size(); 86 | vector> cost(n, vector(n)); 87 | for(int i = 0; i < n; i++) { 88 | Tile& leftTile = leftTiles[i]; 89 | for(int j = 0; j < n; j++) { 90 | Tile& rightTile = rightTiles[j]; 91 | double& dist = cost[i][j]; 92 | int m = leftTile.grid.size(); 93 | dist = 0; 94 | for(int k = 0; k < m; k++) { 95 | dist += sqdistance(leftTile.grid[k], rightTile.grid[k]); 96 | } 97 | } 98 | } 99 | 100 | const vector& assignment = solver.solve(cost); 101 | vector after; 102 | for(int i : assignment) { 103 | after.push_back(rightTiles[i]); 104 | } 105 | rightTiles = after; 106 | } 107 | } 108 | void draw() { 109 | int w = video.getWidth(); 110 | int n = leftTiles.size(); 111 | for(int i = 0; i < n; i++) { 112 | Tile& left = leftTiles[i]; 113 | Tile& right = rightTiles[i]; 114 | rightImage.drawSubsection(left.x, left.y, side, side, right.x, right.y); 115 | leftImage.drawSubsection(w / 2 + right.x, right.y, side, side, left.x, left.y); 116 | } 117 | } 118 | }; 119 | int main() { 120 | ofSetupOpenGL(1280, 720, OF_WINDOW); 121 | ofRunApp(new ofApp()); 122 | } 123 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | The code in this repository is available under the [MIT License](https://secure.wikimedia.org/wikipedia/en/wiki/Mit_license). 2 | 3 | Copyright (c) 2015- Kyle McDonald 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ofxAssignment 2 | 3 | A tool for matching 2d and 3d point clouds, and N-dimensional datasets in a way that minimizes the squared distance between the two datasets. Extremely useful for embedding points on grids. For a visual explanation, see [this notebook](https://github.com/kylemcdonald/CloudToGrid/blob/master/CloudToGrid.ipynb). -------------------------------------------------------------------------------- /src/jv/lap.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************ 2 | * 3 | * lap.cpp 4 | version 1.0 - 4 September 1996 5 | author: Roy Jonker @ MagicLogic Optimization Inc. 6 | e-mail: roy_jonker@magiclogic.com 7 | 8 | Code for Linear Assignment Problem, according to 9 | 10 | "A Shortest Augmenting Path Algorithm for Dense and Sparse Linear 11 | Assignment Problems," Computing 38, 325-340, 1987 12 | 13 | by 14 | 15 | R. Jonker and A. Volgenant, University of Amsterdam. 16 | * 17 | *************************************************************************/ 18 | 19 | #include "lap.h" 20 | 21 | #if !defined TRUE 22 | #define TRUE 1 23 | #endif 24 | #if !defined FALSE 25 | #define FALSE 0 26 | #endif 27 | 28 | cost_t lap(int dim, 29 | cost_t **assigncost, 30 | col_t *rowsol, 31 | row_t *colsol, 32 | cost_t *u, 33 | cost_t *v) 34 | 35 | // input: 36 | // dim - problem size 37 | // assigncost_t - cost_t matrix 38 | 39 | // output: 40 | // rowsol - column assigned to row in solution 41 | // colsol - row assigned to column in solution 42 | // u - dual variables, row reduction numbers 43 | // v - dual variables, column reduction numbers 44 | 45 | { 46 | boolean unassignedfound; 47 | row_t i, imin, numfree = 0, prvnumfree, f, i0, k, freerow, *pred, *free; 48 | col_t j, j1, j2, endofpath, last, low, up, *collist, *matches; 49 | cost_t min, h, umin, usubmin, v2, *d; 50 | 51 | free = new row_t[dim]; // list of unassigned rows. 52 | collist = new col_t[dim]; // list of columns to be scanned in various ways. 53 | matches = new col_t[dim]; // counts how many times a row could be assigned. 54 | d = new cost_t[dim]; // 'cost-distance' in augmenting path calculation. 55 | pred = new row_t[dim]; // row-predecessor of column in augmenting/alternating path. 56 | 57 | // init how many times a row will be assigned in the column reduction. 58 | for (i = 0; i < dim; i++) 59 | matches[i] = 0; 60 | 61 | // COLUMN REDUCTION 62 | for (j = dim-1; j >= 0; j--) // reverse order gives better results. 63 | { 64 | // find minimum cost_t over rows. 65 | min = assigncost[0][j]; 66 | imin = 0; 67 | for (i = 1; i < dim; i++) 68 | if (assigncost[i][j] < min) 69 | { 70 | min = assigncost[i][j]; 71 | imin = i; 72 | } 73 | v[j] = min; 74 | 75 | if (++matches[imin] == 1) 76 | { 77 | // init assignment if minimum row assigned for first time. 78 | rowsol[imin] = j; 79 | colsol[j] = imin; 80 | } 81 | else 82 | colsol[j] = -1; // row already assigned, column not assigned. 83 | } 84 | 85 | // REDUCTION TRANSFER 86 | for (i = 0; i < dim; i++) 87 | if (matches[i] == 0) // fill list of unassigned 'free' rows. 88 | free[numfree++] = i; 89 | else 90 | if (matches[i] == 1) // transfer reduction from rows that are assigned once. 91 | { 92 | j1 = rowsol[i]; 93 | min = BIG; 94 | for (j = 0; j < dim; j++) 95 | if (j != j1) 96 | if (assigncost[i][j] - v[j] < min) 97 | min = assigncost[i][j] - v[j]; 98 | v[j1] = v[j1] - min; 99 | } 100 | 101 | // AUGMENTING ROW REDUCTION 102 | int loopcnt = 0; // do-loop to be done twice. 103 | do 104 | { 105 | loopcnt++; 106 | 107 | // scan all free rows. 108 | // in some cases, a free row may be replaced with another one to be scanned next. 109 | k = 0; 110 | prvnumfree = numfree; 111 | numfree = 0; // start list of rows still free after augmenting row reduction. 112 | while (k < prvnumfree) 113 | { 114 | i = free[k]; 115 | k++; 116 | 117 | // find minimum and second minimum reduced cost_t over columns. 118 | umin = assigncost[i][0] - v[0]; 119 | j1 = 0; 120 | usubmin = BIG; 121 | for (j = 1; j < dim; j++) 122 | { 123 | h = assigncost[i][j] - v[j]; 124 | if (h < usubmin) 125 | if (h >= umin) 126 | { 127 | usubmin = h; 128 | j2 = j; 129 | } 130 | else 131 | { 132 | usubmin = umin; 133 | umin = h; 134 | j2 = j1; 135 | j1 = j; 136 | } 137 | } 138 | 139 | i0 = colsol[j1]; 140 | if (umin < usubmin) 141 | // change the reduction of the minimum column to increase the minimum 142 | // reduced cost_t in the row to the subminimum. 143 | v[j1] = v[j1] - (usubmin - umin); 144 | else // minimum and subminimum equal. 145 | if (i0 >= 0) // minimum column j1 is assigned. 146 | { 147 | // swap columns j1 and j2, as j2 may be unassigned. 148 | j1 = j2; 149 | i0 = colsol[j2]; 150 | } 151 | 152 | // (re-)assign i to j1, possibly de-assigning an i0. 153 | rowsol[i] = j1; 154 | colsol[j1] = i; 155 | 156 | if (i0 >= 0) // minimum column j1 assigned earlier. 157 | if (umin < usubmin) 158 | // put in current k, and go back to that k. 159 | // continue augmenting path i - j1 with i0. 160 | free[--k] = i0; 161 | else 162 | // no further augmenting reduction possible. 163 | // store i0 in list of free rows for next phase. 164 | free[numfree++] = i0; 165 | } 166 | } 167 | while (loopcnt < 2); // repeat once. 168 | 169 | // AUGMENT SOLUTION for each free row. 170 | for (f = 0; f < numfree; f++) 171 | { 172 | freerow = free[f]; // start row of augmenting path. 173 | 174 | // Dijkstra shortest path algorithm. 175 | // runs until unassigned column added to shortest path tree. 176 | for (j = 0; j < dim; j++) 177 | { 178 | d[j] = assigncost[freerow][j] - v[j]; 179 | pred[j] = freerow; 180 | collist[j] = j; // init column list. 181 | } 182 | 183 | low = 0; // columns in 0..low-1 are ready, now none. 184 | up = 0; // columns in low..up-1 are to be scanned for current minimum, now none. 185 | // columns in up..dim-1 are to be considered later to find new minimum, 186 | // at this stage the list simply contains all columns 187 | unassignedfound = FALSE; 188 | do 189 | { 190 | if (up == low) // no more columns to be scanned for current minimum. 191 | { 192 | last = low - 1; 193 | 194 | // scan columns for up..dim-1 to find all indices for which new minimum occurs. 195 | // store these indices between low..up-1 (increasing up). 196 | min = d[collist[up++]]; 197 | for (k = up; k < dim; k++) 198 | { 199 | j = collist[k]; 200 | h = d[j]; 201 | if (h <= min) 202 | { 203 | if (h < min) // new minimum. 204 | { 205 | up = low; // restart list at index low. 206 | min = h; 207 | } 208 | // new index with same minimum, put on undex up, and extend list. 209 | collist[k] = collist[up]; 210 | collist[up++] = j; 211 | } 212 | } 213 | 214 | // check if any of the minimum columns happens to be unassigned. 215 | // if so, we have an augmenting path right away. 216 | for (k = low; k < up; k++) 217 | if (colsol[collist[k]] < 0) 218 | { 219 | endofpath = collist[k]; 220 | unassignedfound = TRUE; 221 | break; 222 | } 223 | } 224 | 225 | if (!unassignedfound) 226 | { 227 | // update 'distances' between freerow and all unscanned columns, via next scanned column. 228 | j1 = collist[low]; 229 | low++; 230 | i = colsol[j1]; 231 | h = assigncost[i][j1] - v[j1] - min; 232 | 233 | for (k = up; k < dim; k++) 234 | { 235 | j = collist[k]; 236 | v2 = assigncost[i][j] - v[j] - h; 237 | if (v2 < d[j]) 238 | { 239 | pred[j] = i; 240 | if (v2 == min) // new column found at same minimum value 241 | if (colsol[j] < 0) 242 | { 243 | // if unassigned, shortest augmenting path is complete. 244 | endofpath = j; 245 | unassignedfound = TRUE; 246 | break; 247 | } 248 | // else add to list to be scanned right away. 249 | else 250 | { 251 | collist[k] = collist[up]; 252 | collist[up++] = j; 253 | } 254 | d[j] = v2; 255 | } 256 | } 257 | } 258 | } 259 | while (!unassignedfound); 260 | 261 | // update column prices. 262 | for (k = 0; k <= last; k++) 263 | { 264 | j1 = collist[k]; 265 | v[j1] = v[j1] + d[j1] - min; 266 | } 267 | 268 | // reset row and column assignments along the alternating path. 269 | do 270 | { 271 | i = pred[endofpath]; 272 | colsol[endofpath] = i; 273 | j1 = endofpath; 274 | endofpath = rowsol[i]; 275 | rowsol[i] = j1; 276 | } 277 | while (i != freerow); 278 | } 279 | 280 | // calculate optimal cost. 281 | cost_t lapcost = 0; 282 | for (i = 0; i < dim; i++) 283 | { 284 | j = rowsol[i]; 285 | u[i] = assigncost[i][j] - v[j]; 286 | lapcost = lapcost + assigncost[i][j]; 287 | } 288 | 289 | // free reserved memory. 290 | delete[] pred; 291 | delete[] free; 292 | delete[] collist; 293 | delete[] matches; 294 | delete[] d; 295 | 296 | return lapcost; 297 | } 298 | 299 | -------------------------------------------------------------------------------- /src/jv/lap.h: -------------------------------------------------------------------------------- 1 | /************************************************************************ 2 | * 3 | * lap.h 4 | version 1.0 - 21 june 1996 5 | author Roy Jonker, MagicLogic Optimization Inc. 6 | 7 | 8 | header file for LAP 9 | * 10 | **************************************************************************/ 11 | 12 | /*************** CONSTANTS *******************/ 13 | 14 | // changing this will change the accuracy 15 | // if it gets closer to 100 it will start to significantly loose accuracy 16 | #define BIG 100000 17 | 18 | /*************** DATA TYPES *******************/ 19 | 20 | typedef int boolean; 21 | 22 | /*************** TYPES *******************/ 23 | 24 | typedef int row_t; 25 | typedef int col_t; 26 | typedef unsigned int cost_t; 27 | 28 | /*************** FUNCTIONS *******************/ 29 | 30 | extern cost_t lap(int dim, cost_t **assigncost, 31 | row_t *rowsol, col_t *colsol, 32 | cost_t *u, cost_t *v); 33 | -------------------------------------------------------------------------------- /src/ofxAssignment.cpp: -------------------------------------------------------------------------------- 1 | #include "ofxAssignment.h" 2 | #include "lap.h" 3 | 4 | float getCost(const ofVec2f& a, const ofVec2f& b) { 5 | return a.squareDistance(b); 6 | } 7 | 8 | float getCost(const ofVec3f& a, const ofVec3f& b) { 9 | return a.squareDistance(b); 10 | } 11 | 12 | float getCost(const vector& a, const vector& b) { 13 | if(a.size() != b.size()) throw; 14 | int n = a.size(); 15 | float sum = 0; 16 | for(int i = 0; i < n; i++) { 17 | float diff = a[i] - b[i]; 18 | sum += diff * diff; 19 | } 20 | return sum; 21 | } 22 | 23 | template 24 | vector> getCost(const vector& a, const vector& b) { 25 | if(a.size() != b.size()) throw; 26 | int n = a.size(); 27 | vector> costs(n, vector(n)); 28 | for(int i = 0; i < n; i++) { 29 | for(int j = 0; j < n; j++) { 30 | costs[i][j] = getCost(a[i], b[j]); 31 | } 32 | } 33 | return costs; 34 | } 35 | 36 | ofVec2f min(const ofVec2f& a, const ofVec2f& b) { 37 | return ofVec2f(MIN(a.x, b.x), 38 | MIN(a.y, b.y)); 39 | } 40 | 41 | ofVec2f max(const ofVec2f& a, const ofVec2f& b) { 42 | return ofVec2f(MAX(a.x, b.x), 43 | MAX(a.y, b.y)); 44 | } 45 | 46 | ofVec2f normalize(ofVec2f& x, const ofVec2f& mi, const ofVec2f& ma) { 47 | x.x -= mi.x; 48 | x.y -= mi.y; 49 | x.x /= (ma.x - mi.x); 50 | x.y /= (ma.y - mi.y); 51 | return x; 52 | } 53 | 54 | ofVec3f min(const ofVec3f& a, const ofVec3f& b) { 55 | return ofVec3f(MIN(a.x, b.x), 56 | MIN(a.y, b.y), 57 | MIN(a.z, b.z)); 58 | } 59 | 60 | ofVec3f max(const ofVec3f& a, const ofVec3f& b) { 61 | return ofVec3f(MAX(a.x, b.x), 62 | MAX(a.y, b.y), 63 | MAX(a.z, b.z)); 64 | } 65 | 66 | ofVec3f normalize(ofVec3f& x, const ofVec3f& mi, const ofVec3f& ma) { 67 | x.x -= mi.x; 68 | x.y -= mi.y; 69 | x.z -= mi.z; 70 | x.x /= (ma.x - mi.x); 71 | x.y /= (ma.y - mi.y); 72 | x.z /= (ma.z - mi.z); 73 | return x; 74 | } 75 | 76 | template 77 | vector min(const vector& a, const vector& b) { 78 | int n = a.size(); 79 | vector result(n); 80 | for(int i = 0; i < n; i++) { 81 | result[i] = MIN(a[i], b[i]); 82 | } 83 | return result; 84 | } 85 | 86 | template 87 | vector max(const vector& a, const vector& b) { 88 | int n = a.size(); 89 | vector result(n); 90 | for(int i = 0; i < n; i++) { 91 | result[i] = MAX(a[i], b[i]); 92 | } 93 | return result; 94 | } 95 | 96 | template 97 | vector normalize(const vector& x, const vector& mi, const vector& ma) { 98 | int n = x.size(); 99 | vector result(n); 100 | for(int i = 0; i < n; i++) { 101 | result[i] = (x[i] - mi[i]) / (ma[i] - mi[i]); 102 | } 103 | return result; 104 | } 105 | 106 | template 107 | void normalizeToLimits(vector& x) { 108 | T xmin, xmax; 109 | bool first = true; 110 | for(const T& point : x) { 111 | if(first) { 112 | xmin = point; 113 | xmax = point; 114 | first = false; 115 | } else { 116 | xmin = min(xmin, point); 117 | xmax = max(xmax, point); 118 | } 119 | } 120 | for(T& point : x) { 121 | point = normalize(point, xmin, xmax); 122 | } 123 | } 124 | 125 | template 126 | float getMax(const vector>& m) { 127 | float max = 0; 128 | for(auto& row : m) { 129 | for(auto& e : row) { 130 | max = MAX(max, e); 131 | } 132 | } 133 | return max; 134 | } 135 | 136 | vector makeGrid(int xSteps, int ySteps) { 137 | vector grid; 138 | for(int y = 0; y < ySteps; y++) { 139 | for(int x = 0; x < xSteps; x++) { 140 | grid.push_back(ofVec2f((float) x / (xSteps - 1), 141 | (float) y / (ySteps - 1))); 142 | } 143 | } 144 | return grid; 145 | } 146 | 147 | vector makeGrid(int xSteps, int ySteps, int zSteps) { 148 | vector grid; 149 | for(int y = 0; y < ySteps; y++) { 150 | for(int x = 0; x < xSteps; x++) { 151 | for(int z = 0; z < zSteps; z++) { 152 | grid.push_back(ofVec3f((float) x / (xSteps - 1), 153 | (float) y / (ySteps - 1), 154 | (float) z / (zSteps - 1))); 155 | } 156 | } 157 | } 158 | return grid; 159 | } 160 | 161 | // these are the available implementations 162 | template vector ofxAssignment::match(vector& a, vector& b, bool normalize); 163 | template vector ofxAssignment::match(vector& a, vector& b, bool normalize); 164 | template vector> ofxAssignment::match>(vector>& a, vector>& b, bool normalize); 165 | 166 | template 167 | vector ofxAssignment::match(vector& a, vector& b, bool normalize) { 168 | if(a.size() != b.size()) throw; 169 | int n = a.size(); 170 | if(normalize) { 171 | normalizeToLimits(a); 172 | normalizeToLimits(b); 173 | } 174 | vector> cost = getCost(a, b); 175 | solve(cost); 176 | vector matched(n); 177 | for(int i = 0; i < n; i++) { 178 | int match = assignment[i]; 179 | matched[i] = b[match]; 180 | } 181 | return matched; 182 | } 183 | 184 | const vector& ofxAssignment::solve(const vector>& cost) { 185 | int dim = cost.size(); 186 | cost_t** assigncost = new cost_t*[dim]; 187 | float scale = BIG / getMax(cost); 188 | for (int i = 0; i < dim; i++) { 189 | assigncost[i] = new cost_t[dim]; 190 | for(int j = 0; j < dim; j++) { 191 | assigncost[i][j] = scale * cost[i][j]; 192 | } 193 | } 194 | 195 | row_t *rowsol = new row_t[dim]; 196 | col_t *colsol = new col_t[dim]; 197 | cost_t *u = new cost_t[dim]; 198 | cost_t *v = new cost_t[dim]; 199 | lap(dim, assigncost, rowsol, colsol, u, v); 200 | 201 | assignment = vector(dim); 202 | for (int i = 0; i < dim; i++) { 203 | assignment[i] = rowsol[i]; 204 | } 205 | 206 | delete [] rowsol; 207 | delete [] colsol; 208 | delete [] u; 209 | delete [] v; 210 | 211 | return assignment; 212 | } -------------------------------------------------------------------------------- /src/ofxAssignment.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | 5 | vector makeGrid(int xSteps, int ySteps); 6 | vector makeGrid(int xSteps, int ySteps, int zSteps); 7 | 8 | class ofxAssignment { 9 | protected: 10 | vector assignment; 11 | public: 12 | 13 | // note that match() will modify a and b if normalize is true! 14 | template 15 | vector match(vector& a, vector& b, bool normalize = true); 16 | 17 | // solve is useful for solving a square cost matrix directly 18 | const vector& solve(const vector>& cost); 19 | }; --------------------------------------------------------------------------------