273
272
lowest_pt = poly->points[0];
276
for (i=1;i<num_new;i++)
275
for (i = 1; i < num_new; i++)
277
276
if (poly->points[i].y < lowest_pt.y)
279
lowest_pt = poly->points[i];
278
lowest_pt = poly->points[i];
283
282
/* sort by angle from lowest point */
285
for (i=0,j=0;i<num_new;i++,j++)
284
for (i = 0, j = 0; i < num_new; i++, j++)
291
gdouble dy = poly->points[i].y - lowest_pt.y;
292
gdouble dx = poly->points[i].x - lowest_pt.x;
290
gdouble dy = poly->points[i].y - lowest_pt.y;
291
gdouble dx = poly->points[i].x - lowest_pt.x;
300
sort_points[j].point = poly->points[i];
301
sort_points[j].angle = atan2 (dy, dx);
293
if (dy == 0 && dx == 0)
299
sort_points[j].point = poly->points[i];
300
sort_points[j].angle = atan2 (dy, dx);
305
qsort (sort_points, num_new-1, sizeof (SortPoint), ipolygon_sort_func);
304
qsort (sort_points, num_new - 1, sizeof (SortPoint), ipolygon_sort_func);
307
306
/* now ensure that all turns as we trace the perimiter are
308
307
counter-clockwise */
312
311
x1 = new_points[1].x - new_points[0].x;
313
312
y1 = new_points[1].y - new_points[0].y;
315
for (i=1,j=2;j<num_new;i++,j++)
314
for (i = 1, j = 2; j < num_new; i++, j++)
317
x2 = sort_points[i].point.x - new_points[j-1].x;
318
y2 = sort_points[i].point.y - new_points[j-1].y;
327
while (x1*y2 - x2*y1 < 0) /* clockwise rotation */
331
x1 = new_points[j-1].x - new_points[j-2].x;
332
y1 = new_points[j-1].y - new_points[j-2].y;
333
x2 = sort_points[i].point.x - new_points[j-1].x;
334
y2 = sort_points[i].point.y - new_points[j-1].y;
316
x2 = sort_points[i].point.x - new_points[j - 1].x;
317
y2 = sort_points[i].point.y - new_points[j - 1].y;
319
if (x2 == 0 && y2 == 0)
326
while (x1 * y2 - x2 * y1 < 0) /* clockwise rotation */
330
x1 = new_points[j - 1].x - new_points[j - 2].x;
331
y1 = new_points[j - 1].y - new_points[j - 2].y;
332
x2 = sort_points[i].point.x - new_points[j - 1].x;
333
y2 = sort_points[i].point.y - new_points[j - 1].y;
336
335
new_points[j] = sort_points[i].point;
402
401
aff_element_compute_color_trans (AffElement *elem)
406
405
if (elem->v.simple_color)
410
mag2 = SQR(elem->v.target_color.r);
411
mag2 += SQR(elem->v.target_color.g);
412
mag2 += SQR(elem->v.target_color.b);
409
mag2 = SQR (elem->v.target_color.r);
410
mag2 += SQR (elem->v.target_color.g);
411
mag2 += SQR (elem->v.target_color.b);
414
413
/* For mag2 == 0, the transformation blows up in general
415
but is well defined for hue_scale == value_scale, so
416
we assume that special case. */
414
but is well defined for hue_scale == value_scale, so
415
we assume that special case. */
421
elem->color_trans.vals[i][j] = 0.0;
417
for (i = 0; i < 3; i++)
419
for (j = 0; j < 4; j++)
420
elem->color_trans.vals[i][j] = 0.0;
423
elem->color_trans.vals[i][i] = elem->v.hue_scale;
422
elem->color_trans.vals[i][i] = elem->v.hue_scale;
430
elem->color_trans.vals[0][j] = elem->v.target_color.r
431
/ mag2 * (elem->v.value_scale - elem->v.hue_scale);
437
elem->color_trans.vals[1][j] = elem->v.target_color.g
438
/ mag2 * (elem->v.value_scale - elem->v.hue_scale);
444
elem->color_trans.vals[2][j] = elem->v.target_color.g
445
/ mag2 * (elem->v.value_scale - elem->v.hue_scale);
448
elem->color_trans.vals[0][0] += elem->v.hue_scale;
449
elem->color_trans.vals[1][1] += elem->v.hue_scale;
450
elem->color_trans.vals[2][2] += elem->v.hue_scale;
453
elem->color_trans.vals[0][3] =
454
(1-elem->v.value_scale)*elem->v.target_color.r;
455
elem->color_trans.vals[1][3] =
456
(1-elem->v.value_scale)*elem->v.target_color.g;
457
elem->color_trans.vals[2][3] =
458
(1-elem->v.value_scale)*elem->v.target_color.b;
427
for (j = 0; j < 3; j++)
429
elem->color_trans.vals[0][j] = elem->v.target_color.r
430
/ mag2 * (elem->v.value_scale - elem->v.hue_scale);
434
for (j = 0; j < 3; j++)
436
elem->color_trans.vals[1][j] = elem->v.target_color.g
437
/ mag2 * (elem->v.value_scale - elem->v.hue_scale);
441
for (j = 0; j < 3; j++)
443
elem->color_trans.vals[2][j] = elem->v.target_color.g
444
/ mag2 * (elem->v.value_scale - elem->v.hue_scale);
447
elem->color_trans.vals[0][0] += elem->v.hue_scale;
448
elem->color_trans.vals[1][1] += elem->v.hue_scale;
449
elem->color_trans.vals[2][2] += elem->v.hue_scale;
451
elem->color_trans.vals[0][3] =
452
(1 - elem->v.value_scale) * elem->v.target_color.r;
453
elem->color_trans.vals[1][3] =
454
(1 - elem->v.value_scale) * elem->v.target_color.g;
455
elem->color_trans.vals[2][3] =
456
(1 - elem->v.value_scale) * elem->v.target_color.b;
463
461
aff3_apply (&elem->color_trans, 1.0, 0.0, 0.0,
464
&elem->v.red_color.r,
465
&elem->v.red_color.g,
466
&elem->v.red_color.b);
462
&elem->v.red_color.r,
463
&elem->v.red_color.g,
464
&elem->v.red_color.b);
467
465
aff3_apply (&elem->color_trans, 0.0, 1.0, 0.0,
468
&elem->v.green_color.r,
469
&elem->v.green_color.g,
470
&elem->v.green_color.b);
466
&elem->v.green_color.r,
467
&elem->v.green_color.g,
468
&elem->v.green_color.b);
471
469
aff3_apply (&elem->color_trans, 0.0, 0.0, 1.0,
472
&elem->v.blue_color.r,
473
&elem->v.blue_color.g,
474
&elem->v.blue_color.b);
470
&elem->v.blue_color.r,
471
&elem->v.blue_color.g,
472
&elem->v.blue_color.b);
475
473
aff3_apply (&elem->color_trans, 0.0, 0.0, 0.0,
476
&elem->v.black_color.r,
477
&elem->v.black_color.g,
478
&elem->v.black_color.b);
474
&elem->v.black_color.r,
475
&elem->v.black_color.g,
476
&elem->v.black_color.b);
482
480
elem->color_trans.vals[0][0] =
483
elem->v.red_color.r - elem->v.black_color.r;
481
elem->v.red_color.r - elem->v.black_color.r;
484
482
elem->color_trans.vals[1][0] =
485
elem->v.red_color.g - elem->v.black_color.g;
483
elem->v.red_color.g - elem->v.black_color.g;
486
484
elem->color_trans.vals[2][0] =
487
elem->v.red_color.b - elem->v.black_color.b;
485
elem->v.red_color.b - elem->v.black_color.b;
489
487
elem->color_trans.vals[0][1] =
490
elem->v.green_color.r - elem->v.black_color.r;
488
elem->v.green_color.r - elem->v.black_color.r;
491
489
elem->color_trans.vals[1][1] =
492
elem->v.green_color.g - elem->v.black_color.g;
490
elem->v.green_color.g - elem->v.black_color.g;
493
491
elem->color_trans.vals[2][1] =
494
elem->v.green_color.b - elem->v.black_color.b;
492
elem->v.green_color.b - elem->v.black_color.b;
496
494
elem->color_trans.vals[0][2] =
497
elem->v.blue_color.r - elem->v.black_color.r;
495
elem->v.blue_color.r - elem->v.black_color.r;
498
496
elem->color_trans.vals[1][2] =
499
elem->v.blue_color.g - elem->v.black_color.g;
497
elem->v.blue_color.g - elem->v.black_color.g;
500
498
elem->color_trans.vals[2][2] =
501
elem->v.blue_color.b - elem->v.black_color.b;
499
elem->v.blue_color.b - elem->v.black_color.b;
503
501
elem->color_trans.vals[0][3] = elem->v.black_color.r;
504
502
elem->color_trans.vals[1][3] = elem->v.black_color.g;
564
scale = elem->v.scale = sqrt (det);
562
scale = elem->v.scale = sqrt (det);
570
scale = elem->v.scale = sqrt (-det);
568
scale = elem->v.scale = sqrt (-det);
575
573
elem->v.theta = atan2 (-t2.a21, t2.a11);
577
575
if (cos (elem->v.theta) == 0.0)
579
elem->v.asym = - t2.a21 / scale / sin(elem->v.theta);
580
elem->v.shear = - sign * t2.a22 / scale / sin(elem->v.theta);
577
elem->v.asym = - t2.a21 / scale / sin (elem->v.theta);
578
elem->v.shear = - sign * t2.a22 / scale / sin (elem->v.theta);
584
elem->v.asym = sign * t2.a11 / scale / cos(elem->v.theta);
585
elem->v.shear = sign *
586
(t2.a12/scale - sin(elem->v.theta)/elem->v.asym)
587
/ cos(elem->v.theta);
582
elem->v.asym = sign * t2.a11 / scale / cos (elem->v.theta);
583
elem->v.shear = sign *
584
(t2.a12/scale - sin (elem->v.theta)/elem->v.asym)
585
/ cos (elem->v.theta);
593
591
aff_element_compute_click_boundary (AffElement *elem,
599
597
gdouble xtot = 0;
600
598
gdouble ytot = 0;
603
gdouble sth,cth; /* sin(theta), cos(theta) */
601
gdouble sth, cth; /* sin(theta), cos(theta) */
602
gdouble axis1, axis2;
605
603
gdouble axis1max, axis2max, axis1min, axis2min;
607
605
/* compute the center of mass of the points */
608
for (i=0; i<num_elements; i++)
606
for (i = 0; i < num_elements; i++)
610
608
xtot += points_x[i];
611
609
ytot += points_y[i];
613
xc = xtot/num_elements;
614
yc = ytot/num_elements;
611
xc = xtot / num_elements;
612
yc = ytot / num_elements;
616
614
/* compute the sum of the (x+iy)^2, and take half the the resulting
617
615
angle (xtot+iytot = A*exp(2i*theta)), to get an average direction */
623
621
xtot += SQR (points_x[i] - xc) - SQR (points_y[i] - yc);
624
622
ytot += 2 * (points_x[i] - xc) * (points_y[i] - yc);
626
theta = 0.5*atan2(ytot,xtot);
624
theta = 0.5 * atan2 (ytot, xtot);
630
628
/* compute the minimum rectangle at angle theta that bounds the points,
631
629
1/2 side lenghs left in axis1, axis2, center in xc, yc */
633
631
axis1max = axis1min = 0.0;
634
632
axis2max = axis2min = 0.0;
635
for (i=0; i<num_elements; i++)
633
for (i = 0; i < num_elements; i++)
637
gdouble proj1 = (points_x[i]-xc)*cth + (points_y[i]-yc)*sth;
638
gdouble proj2 = -(points_x[i]-xc)*sth + (points_y[i]-yc)*cth;
635
gdouble proj1 = (points_x[i] - xc) * cth + (points_y[i] - yc) * sth;
636
gdouble proj2 = -(points_x[i] - xc) * sth + (points_y[i] - yc) * cth;
639
637
if (proj1 < axis1min)
641
639
if (proj1 > axis1max)
643
641
if (proj2 < axis2min)
645
643
if (proj2 > axis2max)
648
axis1 = 0.5*(axis1max - axis1min);
649
axis2 = 0.5*(axis2max - axis2min);
650
xc += 0.5*((axis1max + axis1min)*cth - (axis2max+axis2min)*sth);
651
yc += 0.5*((axis1max + axis1min)*sth + (axis2max+axis2min)*cth);
646
axis1 = 0.5 * (axis1max - axis1min);
647
axis2 = 0.5 * (axis2max - axis2min);
648
xc += 0.5 * ((axis1max + axis1min) * cth - (axis2max + axis2min) * sth);
649
yc += 0.5 * ((axis1max + axis1min) * sth + (axis2max + axis2min) * cth);
653
651
/* if the the rectangle is less than 10 pixels in any dimension,
654
652
make it click_boundary, otherwise set click_boundary = draw_boundary */
656
654
if (axis1 < 8.0 || axis2 < 8.0)
658
GdkPoint *points = g_new (GdkPoint,4);
656
GdkPoint *points = g_new (GdkPoint, 4);
660
elem->click_boundary = g_new (IPolygon,1);
658
elem->click_boundary = g_new (IPolygon, 1);
661
659
elem->click_boundary->points = points;
662
660
elem->click_boundary->npoints = 4;
664
662
if (axis1 < 8.0) axis1 = 8.0;
665
663
if (axis2 < 8.0) axis2 = 8.0;
667
points[0].x = xc + axis1*cth - axis2*sth;
668
points[0].y = yc + axis1*sth + axis2*cth;
669
points[1].x = xc - axis1*cth - axis2*sth;
670
points[1].y = yc - axis1*sth + axis2*cth;
671
points[2].x = xc - axis1*cth + axis2*sth;
672
points[2].y = yc - axis1*sth - axis2*cth;
673
points[3].x = xc + axis1*cth + axis2*sth;
674
points[3].y = yc + axis1*sth - axis2*cth;
665
points[0].x = xc + axis1 * cth - axis2 * sth;
666
points[0].y = yc + axis1 * sth + axis2 * cth;
667
points[1].x = xc - axis1 * cth - axis2 * sth;
668
points[1].y = yc - axis1 * sth + axis2 * cth;
669
points[2].x = xc - axis1 * cth + axis2 * sth;
670
points[2].y = yc - axis1 * sth - axis2 * cth;
671
points[3].x = xc + axis1 * cth + axis2 * sth;
672
points[3].y = yc + axis1 * sth - axis2 * cth;
677
675
elem->click_boundary = elem->draw_boundary;
699
697
points_x = g_new (gdouble, num_elements);
700
698
points_y = g_new (gdouble, num_elements);
702
for (i=0;i<num_elements;i++)
700
for (i = 0; i < num_elements; i++)
704
aff2_apply (&elem->trans,elements[i]->v.x*width,elements[i]->v.y*width,
702
aff2_apply (&elem->trans,
703
elements[i]->v.x * width, elements[i]->v.y * width,
705
704
&points_x[i],&points_y[i]);
706
705
tmp_poly.points[i].x = (gint)points_x[i];
707
706
tmp_poly.points[i].y = (gint)points_y[i];
710
709
elem->draw_boundary = ipolygon_convex_hull (&tmp_poly);
711
aff_element_compute_click_boundary (elem,num_elements,points_x,points_y);
710
aff_element_compute_click_boundary (elem, num_elements, points_x, points_y);
713
712
g_free (tmp_poly.points);
717
716
aff_element_draw (AffElement *elem,
726
725
PangoRectangle rect;
822
821
brush = g_new (guchar, SQR (*brush_size));
824
for (i=0 ; i < *brush_size; i++)
823
for (i = 0; i < *brush_size; i++)
826
825
for (j = 0; j < *brush_size; j++)
829
gdouble d = sqrt (SQR (i - *brush_offset) +
828
gdouble d = sqrt (SQR (i - *brush_offset) +
830
829
SQR (j - *brush_offset));
832
if (d - 0.5 * G_SQRT2 > radius)
834
else if (d + 0.5 * G_SQRT2 < radius)
837
for (ii = 0; ii < 10; ii++)
838
for (jj = 0; jj < 10; jj++)
840
d = sqrt (SQR (i - *brush_offset + ii * 0.1 - 0.45) +
831
if (d - 0.5 * G_SQRT2 > radius)
833
else if (d + 0.5 * G_SQRT2 < radius)
836
for (ii = 0; ii < 10; ii++)
837
for (jj = 0; jj < 10; jj++)
839
d = sqrt (SQR (i - *brush_offset + ii * 0.1 - 0.45) +
841
840
SQR (j - *brush_offset + jj * 0.1 - 0.45));
842
pixel += (d < radius) / 100.0;
841
pixel += (d < radius) / 100.0;
845
brush[i**brush_size + j] = 255.999 * pixel;
844
brush[i * *brush_size + j] = 255.999 * pixel;
847
846
#ifdef DEBUG_BRUSH
848
putchar(brush_chars[(gint)(pixel * 3.999)]);
847
putchar(brush_chars[(gint)(pixel * 3.999)]);
850
849
#endif /* DEBUG_BRUSH */
852
851
#ifdef DEBUG_BRUSH
854
853
#endif /* DEBUG_BRUSH */
856
855
#ifdef DEBUG_BRUSH
857
printf("Brush total / area = %f\n",totpix/SQR(ifsvals->subdivide));
856
printf ("Brush total / area = %f\n", totpix / SQR (ifsvals->subdivide));
858
857
#endif /* DEBUG_BRUSH */
863
862
ifs_render (AffElement **elements,
868
IfsComposeVals *vals,
867
IfsComposeVals *vals,
896
896
fprob = g_new (gdouble, num_elements);
897
897
prob = g_new (guint32, num_elements);
899
for (i=0;i<num_elements;i++)
900
for (i = 0; i < num_elements; i++)
901
aff_element_compute_trans(elements[i],width*subdivide,height*subdivide,
902
vals->center_x, vals->center_y);
902
aff_element_compute_trans(elements[i],
904
elements[i]->trans.a11 * elements[i]->trans.a22
905
- elements[i]->trans.a12 * elements[i]->trans.a21);
908
elements[i]->trans.a11 * elements[i]->trans.a22
909
- elements[i]->trans.a12 * elements[i]->trans.a21);
906
911
/* As a heuristic, if the determinant is really small, it's
907
probably a line element, so increase the probability so
912
probably a line element, so increase the probability so
909
915
/* FIXME: figure out what 0.01 really should be */
910
916
if (fprob[i] < 0.01)
912
919
fprob[i] *= elements[i]->v.prob;
918
925
for (i = 0; i < num_elements; i++)
920
psum += (guint32) -1 * (fprob[i]/pt);
927
psum += (guint32) -1 * (fprob[i] / pt);
923
prob[i-1] = (guint32) -1; /* make sure we don't get bitten
931
prob[i - 1] = (guint32) -1; /* make sure we don't get bitten by roundoff */
925
933
/* create the brush */
927
brush = create_brush (vals,&brush_size,&brush_offset);
935
brush = create_brush (vals, &brush_size, &brush_offset);
932
940
/* now run the iteration */
933
for (i=0;i<nsteps;i++)
941
for (i = 0; i < nsteps; i++)
935
if (!preview && !(i % 5000))
936
gimp_progress_update ((gdouble) i / (gdouble) nsteps);
943
if (!preview && (i > next_progress))
945
next_progress = i + nsteps / 32 + 100;
946
gimp_progress_update ((gdouble) i / (gdouble) nsteps);
937
949
p0 = g_random_int ();
939
952
while (p0 > prob[k])
942
aff2_apply(&elements[k]->trans,x,y,&x,&y);
943
aff3_apply(&elements[k]->color_trans,r,g,b,&r,&g,&b);
946
ri = (gint) (254.999 * r + 0.5);
947
gi = (gint) (254.999 * g + 0.5);
948
bi = (gint) (254.999 * b + 0.5);
955
aff2_apply (&elements[k]->trans, x, y, &x, &y);
956
aff3_apply (&elements[k]->color_trans, r, g, b, &r, &g, &b);
961
ri = (gint) (255.0 * r + 0.5);
962
gi = (gint) (255.0 * g + 0.5);
963
bi = (gint) (255.0 * b + 0.5);
965
if ((ri < 0) || (ri > 255) ||
966
(gi < 0) || (gi > 255) ||
967
(bi < 0) || (bi > 255))
952
if ((x<width) && (y<(band_y+band_height)) &&
953
(x >= 0) && (y >= band_y) &&
954
(ri >= 0) && (ri < 256) &&
955
(gi >= 0) && (gi < 256) &&
956
(bi >= 0) && (bi < 256))
958
ptr = data + 3 * (((gint)(y-band_y))*width + (gint)x);
972
if ((x < width) && (y < (band_y + band_height)) &&
973
(x >= 0) && (y >= band_y))
975
ptr = data + 3 * (((gint) (y - band_y)) * width + (gint) x);
965
if ((ri >= 0) && (ri < 256) &&
966
(gi >= 0) && (gi < 256) &&
967
(bi >= 0) && (bi < 256))
978
gint jj0 = floor(y-brush_offset-band_y*subdivide);
979
gint ii0 = floor(x-brush_offset);
994
if (jj0 + brush_size >= subdivide * band_height)
995
jjmax = subdivide * band_height - jj0;
999
if (ii0 + brush_size >= subdivide * width)
1000
iimax = subdivide * width - ii0;
1004
for (jj = jjmin; jj < jjmax; jj++)
1005
for (ii = iimin; ii < iimax; ii++)
1007
index = (jj0 + jj) * width * subdivide + ii0 + ii;
1008
n_hits = nhits[index];
1012
m_pix = brush[jj*brush_size+ii];
1015
nhits[index] = ++n_hits;
1016
m_old = mask[index];
1017
m_new = m_old + m_pix - m_old*m_pix/255;
1018
mask[index] = m_new;
1020
/* relative probability that old colored pixel is on top */
1021
old_scale = m_old*(255*n_hits-m_pix);
1022
/* relative probability that new colored pixel is on top */
1023
pix_scale = m_pix*((255-m_old)*n_hits+m_old);
1025
ptr = data + 3*index;
1026
*ptr = ( old_scale * (*ptr) + pix_scale * ri ) /
1027
( old_scale + pix_scale );
1029
*ptr = ( old_scale * (*ptr) + pix_scale * gi ) /
1030
( old_scale + pix_scale );
1032
*ptr = ( old_scale * (*ptr) + pix_scale * bi ) /
1033
( old_scale + pix_scale );
984
if ((x < width * subdivide) && (y < height * subdivide) &&
985
(x >= 0) && (y >= 0))
989
gint jj0 = floor (y - brush_offset - band_y * subdivide);
990
gint ii0 = floor (x - brush_offset);
1006
if (jj0 + brush_size >= subdivide * band_height)
1007
jjmax = subdivide * band_height - jj0;
1011
if (ii0 + brush_size >= subdivide * width)
1012
iimax = subdivide * width - ii0;
1016
for (jj = jjmin; jj < jjmax; jj++)
1017
for (ii = iimin; ii < iimax; ii++)
1025
gint index = (jj0 + jj) * width * subdivide + ii0 + ii;
1027
n_hits = nhits[index];
1031
m_pix = brush[jj * brush_size + ii];
1035
nhits[index] = ++n_hits;
1036
m_old = mask[index];
1037
m_new = m_old + m_pix - m_old * m_pix / 255;
1038
mask[index] = m_new;
1040
/* relative probability that old colored pixel is on top */
1041
old_scale = m_old * (255 * n_hits - m_pix);
1043
/* relative probability that new colored pixel is on top */
1044
pix_scale = m_pix * ((255 - m_old) * n_hits + m_old);
1046
ptr = data + 3 * index;
1048
*ptr = ((old_scale * (*ptr) + pix_scale * ri) /
1049
(old_scale + pix_scale));
1052
*ptr = ((old_scale * (*ptr) + pix_scale * gi) /
1053
(old_scale + pix_scale));
1056
*ptr = ((old_scale * (*ptr) + pix_scale * bi) /
1057
(old_scale + pix_scale));
1036
1061
} /* main iteration */
1064
gimp_progress_update (1.0);
1038
1066
g_free (brush);
1040
1068
g_free (fprob);