Blender V2.61 - r43446

sketch.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * Contributor(s): none yet.
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00028 #include <string.h>
00029 #include <math.h>
00030 #include <float.h>
00031 
00032 #include "MEM_guardedalloc.h"
00033 
00034 #include "BLI_blenlib.h"
00035 #include "BLI_math.h"
00036 #include "BLI_utildefines.h"
00037 
00038 #include "BKE_sketch.h"
00039 
00040 
00041 #include "DNA_userdef_types.h"
00042 
00043 void freeSketch(SK_Sketch *sketch)
00044 {
00045     SK_Stroke *stk, *next;
00046 
00047     for (stk = sketch->strokes.first; stk; stk = next)
00048     {
00049         next = stk->next;
00050 
00051         sk_freeStroke(stk);
00052     }
00053 
00054     BLI_freelistN(&sketch->depth_peels);
00055 
00056     MEM_freeN(sketch);
00057 }
00058 
00059 SK_Sketch* createSketch(void)
00060 {
00061     SK_Sketch *sketch;
00062 
00063     sketch = MEM_callocN(sizeof(SK_Sketch), "SK_Sketch");
00064 
00065     sketch->active_stroke = NULL;
00066     sketch->gesture = NULL;
00067 
00068     sketch->strokes.first = NULL;
00069     sketch->strokes.last = NULL;
00070 
00071     return sketch;
00072 }
00073 
00074 void sk_initPoint(SK_Point *pt, SK_DrawData *dd, float *no)
00075 {
00076     if (no)
00077     {
00078         normalize_v3_v3(pt->no, no);
00079     }
00080     else
00081     {
00082         pt->no[0] = 0;
00083         pt->no[1] = 0;
00084         pt->no[2] = 1;
00085     }
00086     pt->p2d[0] = dd->mval[0];
00087     pt->p2d[1] = dd->mval[1];
00088     /* more init code here */
00089 }
00090 
00091 void sk_copyPoint(SK_Point *dst, SK_Point *src)
00092 {
00093     memcpy(dst, src, sizeof(SK_Point));
00094 }
00095 
00096 void sk_allocStrokeBuffer(SK_Stroke *stk)
00097 {
00098     stk->points = MEM_callocN(sizeof(SK_Point) * stk->buf_size, "SK_Point buffer");
00099 }
00100 
00101 void sk_freeStroke(SK_Stroke *stk)
00102 {
00103     MEM_freeN(stk->points);
00104     MEM_freeN(stk);
00105 }
00106 
00107 SK_Stroke* sk_createStroke(void)
00108 {
00109     SK_Stroke *stk;
00110 
00111     stk = MEM_callocN(sizeof(SK_Stroke), "SK_Stroke");
00112 
00113     stk->selected = 0;
00114     stk->nb_points = 0;
00115     stk->buf_size = SK_Stroke_BUFFER_INIT_SIZE;
00116 
00117     sk_allocStrokeBuffer(stk);
00118 
00119     return stk;
00120 }
00121 
00122 void sk_shrinkStrokeBuffer(SK_Stroke *stk)
00123 {
00124     if (stk->nb_points < stk->buf_size)
00125     {
00126         SK_Point *old_points = stk->points;
00127 
00128         stk->buf_size = stk->nb_points;
00129 
00130         sk_allocStrokeBuffer(stk);
00131 
00132         memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
00133 
00134         MEM_freeN(old_points);
00135     }
00136 }
00137 
00138 void sk_growStrokeBuffer(SK_Stroke *stk)
00139 {
00140     if (stk->nb_points == stk->buf_size)
00141     {
00142         SK_Point *old_points = stk->points;
00143 
00144         stk->buf_size *= 2;
00145 
00146         sk_allocStrokeBuffer(stk);
00147 
00148         memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
00149 
00150         MEM_freeN(old_points);
00151     }
00152 }
00153 
00154 void sk_growStrokeBufferN(SK_Stroke *stk, int n)
00155 {
00156     if (stk->nb_points + n > stk->buf_size)
00157     {
00158         SK_Point *old_points = stk->points;
00159 
00160         while (stk->nb_points + n > stk->buf_size)
00161         {
00162             stk->buf_size *= 2;
00163         }
00164 
00165         sk_allocStrokeBuffer(stk);
00166 
00167         memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
00168 
00169         MEM_freeN(old_points);
00170     }
00171 }
00172 
00173 
00174 void sk_replaceStrokePoint(SK_Stroke *stk, SK_Point *pt, int n)
00175 {
00176     memcpy(stk->points + n, pt, sizeof(SK_Point));
00177 }
00178 
00179 void sk_insertStrokePoint(SK_Stroke *stk, SK_Point *pt, int n)
00180 {
00181     int size = stk->nb_points - n;
00182 
00183     sk_growStrokeBuffer(stk);
00184 
00185     memmove(stk->points + n + 1, stk->points + n, size * sizeof(SK_Point));
00186 
00187     memcpy(stk->points + n, pt, sizeof(SK_Point));
00188 
00189     stk->nb_points++;
00190 }
00191 
00192 void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt)
00193 {
00194     sk_growStrokeBuffer(stk);
00195 
00196     memcpy(stk->points + stk->nb_points, pt, sizeof(SK_Point));
00197 
00198     stk->nb_points++;
00199 }
00200 
00201 void sk_insertStrokePoints(SK_Stroke *stk, SK_Point *pts, int len, int start, int end)
00202 {
00203     int size = end - start + 1;
00204 
00205     sk_growStrokeBufferN(stk, len - size);
00206 
00207     if (len != size)
00208     {
00209         int tail_size = stk->nb_points - end + 1;
00210 
00211         memmove(stk->points + start + len, stk->points + end + 1, tail_size * sizeof(SK_Point));
00212     }
00213 
00214     memcpy(stk->points + start, pts, len * sizeof(SK_Point));
00215 
00216     stk->nb_points += len - size;
00217 }
00218 
00219 void sk_trimStroke(SK_Stroke *stk, int start, int end)
00220 {
00221     int size = end - start + 1;
00222 
00223     if (start > 0)
00224     {
00225         memmove(stk->points, stk->points + start, size * sizeof(SK_Point));
00226     }
00227 
00228     stk->nb_points = size;
00229 }
00230 
00231 void sk_straightenStroke(SK_Stroke *stk, int start, int end, float p_start[3], float p_end[3])
00232 {
00233     SK_Point pt1, pt2;
00234     SK_Point *prev, *next;
00235     float delta_p[3];
00236     int i, total;
00237 
00238     total = end - start;
00239 
00240     sub_v3_v3v3(delta_p, p_end, p_start);
00241 
00242     prev = stk->points + start;
00243     next = stk->points + end;
00244 
00245     copy_v3_v3(pt1.p, p_start);
00246     copy_v3_v3(pt1.no, prev->no);
00247     pt1.mode = prev->mode;
00248     pt1.type = prev->type;
00249 
00250     copy_v3_v3(pt2.p, p_end);
00251     copy_v3_v3(pt2.no, next->no);
00252     pt2.mode = next->mode;
00253     pt2.type = next->type;
00254 
00255     sk_insertStrokePoint(stk, &pt1, start + 1); /* insert after start */
00256     sk_insertStrokePoint(stk, &pt2, end + 1); /* insert before end (since end was pushed back already) */
00257 
00258     for (i = 1; i < total; i++)
00259     {
00260         float delta = (float)i / (float)total;
00261         float *p = stk->points[start + 1 + i].p;
00262 
00263         VECCOPY(p, delta_p);
00264         mul_v3_fl(p, delta);
00265         add_v3_v3(p, p_start);
00266     }
00267 }
00268 
00269 void sk_polygonizeStroke(SK_Stroke *stk, int start, int end)
00270 {
00271     int offset;
00272     int i;
00273 
00274     /* find first exact points outside of range */
00275     for (;start > 0; start--)
00276     {
00277         if (stk->points[start].type == PT_EXACT)
00278         {
00279             break;
00280         }
00281     }
00282 
00283     for (;end < stk->nb_points - 1; end++)
00284     {
00285         if (stk->points[end].type == PT_EXACT)
00286         {
00287             break;
00288         }
00289     }
00290 
00291     offset = start + 1;
00292 
00293     for (i = start + 1; i < end; i++)
00294     {
00295         if (stk->points[i].type == PT_EXACT)
00296         {
00297             if (offset != i)
00298             {
00299                 memcpy(stk->points + offset, stk->points + i, sizeof(SK_Point));
00300             }
00301 
00302             offset++;
00303         }
00304     }
00305 
00306     /* some points were removes, move end of array */
00307     if (offset < end)
00308     {
00309         int size = stk->nb_points - end;
00310         memmove(stk->points + offset, stk->points + end, size * sizeof(SK_Point));
00311         stk->nb_points = offset + size;
00312     }
00313 }
00314 
00315 void sk_flattenStroke(SK_Stroke *stk, int start, int end)
00316 {
00317     float normal[3], distance[3];
00318     float limit;
00319     int i, total;
00320 
00321     total = end - start + 1;
00322 
00323     copy_v3_v3(normal, stk->points[start].no);
00324 
00325     sub_v3_v3v3(distance, stk->points[end].p, stk->points[start].p);
00326     project_v3_v3v3(normal, distance, normal);
00327     limit = normalize_v3(normal);
00328 
00329     for (i = 1; i < total - 1; i++)
00330     {
00331         float d = limit * i / total;
00332         float offset[3];
00333         float *p = stk->points[start + i].p;
00334 
00335         sub_v3_v3v3(distance, p, stk->points[start].p);
00336         project_v3_v3v3(distance, distance, normal);
00337 
00338         VECCOPY(offset, normal);
00339         mul_v3_fl(offset, d);
00340 
00341         sub_v3_v3(p, distance);
00342         add_v3_v3(p, offset);
00343     }
00344 }
00345 
00346 void sk_removeStroke(SK_Sketch *sketch, SK_Stroke *stk)
00347 {
00348     if (sketch->active_stroke == stk)
00349     {
00350         sketch->active_stroke = NULL;
00351     }
00352 
00353     BLI_remlink(&sketch->strokes, stk);
00354     sk_freeStroke(stk);
00355 }
00356 
00357 void sk_reverseStroke(SK_Stroke *stk)
00358 {
00359     SK_Point *old_points = stk->points;
00360     int i = 0;
00361 
00362     sk_allocStrokeBuffer(stk);
00363 
00364     for (i = 0; i < stk->nb_points; i++)
00365     {
00366         sk_copyPoint(stk->points + i, old_points + stk->nb_points - 1 - i);
00367     }
00368 
00369     MEM_freeN(old_points);
00370 }
00371 
00372 
00373 /* Ramer-Douglas-Peucker algorithm for line simplification */
00374 void sk_filterStroke(SK_Stroke *stk, int start, int end)
00375 {
00376     SK_Point *old_points = stk->points;
00377     int nb_points = stk->nb_points;
00378     char *marked = NULL;
00379     char work;
00380     int i;
00381 
00382     if (start == -1)
00383     {
00384         start = 0;
00385         end = stk->nb_points - 1;
00386     }
00387 
00388     sk_allocStrokeBuffer(stk);
00389     stk->nb_points = 0;
00390 
00391     /* adding points before range */
00392     for (i = 0; i < start; i++)
00393     {
00394         sk_appendStrokePoint(stk, old_points + i);
00395     }
00396 
00397     marked = MEM_callocN(nb_points, "marked array");
00398     marked[start] = 1;
00399     marked[end] = 1;
00400     
00401     work = 1;
00402     
00403     /* while still reducing */
00404     while (work)
00405     {
00406         int ls, le;
00407         work = 0;
00408         
00409         ls = start;
00410         le = start+1;
00411         
00412         /* while not over interval */
00413         while (ls < end)
00414         {
00415             int max_i = 0;
00416             short v1[2];
00417             float max_dist = 16; /* more than 4 pixels */
00418             
00419             /* find the next marked point */
00420             while(marked[le] == 0)
00421             {
00422                 le++;
00423             }
00424             
00425             /* perpendicular vector to ls-le */
00426             v1[1] = old_points[le].p2d[0] - old_points[ls].p2d[0]; 
00427             v1[0] = old_points[ls].p2d[1] - old_points[le].p2d[1]; 
00428             
00429 
00430             for( i = ls + 1; i < le; i++ )
00431             {
00432                 float mul;
00433                 float dist;
00434                 short v2[2];
00435                 
00436                 v2[0] = old_points[i].p2d[0] - old_points[ls].p2d[0]; 
00437                 v2[1] = old_points[i].p2d[1] - old_points[ls].p2d[1];
00438                 
00439                 if (v2[0] == 0 && v2[1] == 0)
00440                 {
00441                     continue;
00442                 }
00443 
00444                 mul = (float)(v1[0]*v2[0] + v1[1]*v2[1]) / (float)(v2[0]*v2[0] + v2[1]*v2[1]);
00445                 
00446                 dist = mul * mul * (v2[0]*v2[0] + v2[1]*v2[1]);
00447                 
00448                 if (dist > max_dist)
00449                 {
00450                     max_dist = dist;
00451                     max_i = i;
00452                 }
00453             }
00454             
00455             if (max_i != 0)
00456             {
00457                 work = 1;
00458                 marked[max_i] = 1;
00459             }
00460             
00461             ls = le;
00462             le = ls + 1;
00463         }
00464     }
00465     
00466 
00467     /* adding points after range */
00468     for (i = start; i <= end; i++)
00469     {
00470         if (marked[i])
00471         {
00472             sk_appendStrokePoint(stk, old_points + i);
00473         }
00474     }
00475 
00476     MEM_freeN(marked);
00477 
00478     /* adding points after range */
00479     for (i = end + 1; i < nb_points; i++)
00480     {
00481         sk_appendStrokePoint(stk, old_points + i);
00482     }
00483 
00484     MEM_freeN(old_points);
00485 
00486     sk_shrinkStrokeBuffer(stk);
00487 }
00488 
00489 
00490 void sk_filterLastContinuousStroke(SK_Stroke *stk)
00491 {
00492     int start, end;
00493 
00494     end = stk->nb_points -1;
00495 
00496     for (start = end - 1; start > 0 && stk->points[start].type == PT_CONTINUOUS; start--)
00497     {
00498         /* nothing to do here*/
00499     }
00500 
00501     if (end - start > 1)
00502     {
00503         sk_filterStroke(stk, start, end);
00504     }
00505 }
00506 
00507 SK_Point *sk_lastStrokePoint(SK_Stroke *stk)
00508 {
00509     SK_Point *pt = NULL;
00510 
00511     if (stk->nb_points > 0)
00512     {
00513         pt = stk->points + (stk->nb_points - 1);
00514     }
00515 
00516     return pt;
00517 }
00518 
00519 void sk_endContinuousStroke(SK_Stroke *stk)
00520 {
00521     stk->points[stk->nb_points - 1].type = PT_EXACT;
00522 }
00523 
00524 void sk_updateNextPoint(SK_Sketch *sketch, SK_Stroke *stk)
00525 {
00526     if (stk)
00527     {
00528         memcpy(&sketch->next_point, stk->points[stk->nb_points - 1].p, sizeof(SK_Point));
00529     }
00530 }
00531 
00532 int sk_stroke_filtermval(SK_DrawData *dd)
00533 {
00534     int retval = 0;
00535     if (ABS(dd->mval[0] - dd->previous_mval[0]) + ABS(dd->mval[1] - dd->previous_mval[1]) > U.gp_manhattendist)
00536     {
00537         retval = 1;
00538     }
00539 
00540     return retval;
00541 }
00542 
00543 void sk_initDrawData(SK_DrawData *dd, const int mval[2])
00544 {
00545     dd->mval[0] = mval[0];
00546     dd->mval[1] = mval[1];
00547     dd->previous_mval[0] = -1;
00548     dd->previous_mval[1] = -1;
00549     dd->type = PT_EXACT;
00550 }
00551 
00552 
00553 void sk_deleteSelectedStrokes(SK_Sketch *sketch)
00554 {
00555     SK_Stroke *stk, *next;
00556 
00557     for (stk = sketch->strokes.first; stk; stk = next)
00558     {
00559         next = stk->next;
00560 
00561         if (stk->selected == 1)
00562         {
00563             sk_removeStroke(sketch, stk);
00564         }
00565     }
00566 }
00567 
00568 void sk_selectAllSketch(SK_Sketch *sketch, int mode)
00569 {
00570     SK_Stroke *stk = NULL;
00571 
00572     if (mode == -1)
00573     {
00574         for (stk = sketch->strokes.first; stk; stk = stk->next)
00575         {
00576             stk->selected = 0;
00577         }
00578     }
00579     else if (mode == 0)
00580     {
00581         for (stk = sketch->strokes.first; stk; stk = stk->next)
00582         {
00583             stk->selected = 1;
00584         }
00585     }
00586     else if (mode == 1)
00587     {
00588         int selected = 1;
00589 
00590         for (stk = sketch->strokes.first; stk; stk = stk->next)
00591         {
00592             selected &= stk->selected;
00593         }
00594 
00595         selected ^= 1;
00596 
00597         for (stk = sketch->strokes.first; stk; stk = stk->next)
00598         {
00599             stk->selected = selected;
00600         }
00601     }
00602 }