diff options
author | Achil | 2022-09-06 18:56:51 +0200 |
---|---|---|
committer | Achil | 2022-09-06 18:56:51 +0200 |
commit | 5bce61c04e589e368d534c4797711ac73c1e1f23 (patch) | |
tree | 299f2b64723a5c9697937f651cecf1416604baad /Python/build/lib.linux-x86_64-2.7/Zinc/geometry.py | |
parent | b60b3de318b4e621518681cc2824b4d9c605ae9e (diff) | |
download | tkzinc-5bce61c04e589e368d534c4797711ac73c1e1f23.zip tkzinc-5bce61c04e589e368d534c4797711ac73c1e1f23.tar.gz tkzinc-5bce61c04e589e368d534c4797711ac73c1e1f23.tar.bz2 tkzinc-5bce61c04e589e368d534c4797711ac73c1e1f23.tar.xz |
Daniel Etienne pre release for Bullseye
Diffstat (limited to 'Python/build/lib.linux-x86_64-2.7/Zinc/geometry.py')
-rwxr-xr-x | Python/build/lib.linux-x86_64-2.7/Zinc/geometry.py | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/Python/build/lib.linux-x86_64-2.7/Zinc/geometry.py b/Python/build/lib.linux-x86_64-2.7/Zinc/geometry.py new file mode 100755 index 0000000..4063b61 --- /dev/null +++ b/Python/build/lib.linux-x86_64-2.7/Zinc/geometry.py @@ -0,0 +1,410 @@ +# -*- coding: iso-8859-1 -*- +""" +# Geometrical basic Functions : +# ----------------------------- +# perpendicular_point +# line_angle +# linenormal +# vertex_angle +# arc_pts +# rad_point +# bezier_compute +# bezier_segment +# bezier_point +""" + +from math import pi, radians, atan2, sin, cos + +# limite globale d'approximation courbe bezier +bezierClosenessThreshold = .2 +def perpendicular_point (point, line): + """ + #--------------------------------------------------------------------------- + # Graphics::perpendicular_point + # retourne les coordonnées du point perpendiculaire abaissé d'un point + # sur une ligne + #--------------------------------------------------------------------------- + # paramètres : + # point : <coords> coordonnées du point de référence + # line : <coordsList> coordonnées des 2 points de la ligne de référence + #--------------------------------------------------------------------------- + """ + (p1, p2) = line + + # cas partiuculier de lignes ortho. + min_dist = .01 + if (abs(p2[1] - p1[1]) < min_dist) : + # la ligne de référence est horizontale + return (point[0], p1[1]) + + elif (abs(p2[0] - p1[0]) < min_dist) : + # la ligne de référence est verticale + return (p1[0], point[1]) + + a1 = float(p2[1] - p1[1]) / float(p2[0] - p1[0]) + b1 = p1[1] - (a1 * p1[0]) + + a2 = -1.0 / a1 + b2 = point[1] - (a2 * point[0]) + + x = (b2 - b1) / (a1 - a2) + y = (a1 * x) + b1 + + return (x, y) + +def line_angle(startpoint, endpoint): + """ + #--------------------------------------------------------------------------- + # Graphics::line_angle + # retourne l'angle d'un point par rapport à un centre de référence + #--------------------------------------------------------------------------- + # paramètres : + # startpoint : <coords> coordonnées du point de départ du segment + # endpoint : <coords> coordonnées du point d'extremité du segment + #--------------------------------------------------------------------------- + """ + angle = atan2(endpoint[1] - startpoint[1], endpoint[0] - startpoint[0]) + + angle += pi/2 + angle *= float(180)/pi + if (angle < 0): + angle += 360 + + return angle + +def linenormal(startpoint, endpoint): + """ + #--------------------------------------------------------------------------- + # Graphics::linenormal + # retourne la valeur d'angle perpendiculaire à une ligne + #--------------------------------------------------------------------------- + # paramètres : + # startpoint : <coords> coordonnées du point de départ du segment + # endpoint : <coords> coordonnées du point d'extremité du segment + #--------------------------------------------------------------------------- + """ + angle = line_angle(startpoint, endpoint) + 90 + + if (angle > 360): + angle -= 360 + return angle + +def vertex_angle(pt0, pt1, pt2): + """ + #--------------------------------------------------------------------------- + # Graphics::vertex_angle + # retourne la valeur de l'angle formée par 3 points + # ainsi que l'angle de la bisectrice + #--------------------------------------------------------------------------- + # paramètres : + # pt0 : <coords> coordonnées du premier point de définition de l'angle + # pt1 : <coords> coordonnées du deuxième point de définition de l'angle + # pt2 : <coords> coordonnées du troisième point de définition de l'angle + #--------------------------------------------------------------------------- + """ + angle1 = line_angle(pt0, pt1) + angle2 = line_angle(pt2, pt1) + + if angle2 < angle1 : + angle2 += 360 + alpha = angle2 - angle1 + bisectrice = angle1 + (float(alpha)/2) + + return (alpha, bisectrice) + + +def arc_pts(center, radius, **options): + """ + #--------------------------------------------------------------------------- + # Graphics::arc_pts + # calcul des points constitutif d'un arc + #--------------------------------------------------------------------------- + # paramètres : + # center : <coordonnées> centre de l'arc, + # radius : <dimension> rayon de l'arc, + # options : + # -angle : <angle> angle de départ en degré de l'arc (par défaut 0) + # -extent : <angle> delta angulaire en degré de l'arc (par défaut 360), + # -step : <dimension> pas de progresion en degré (par défaut 10) + #--------------------------------------------------------------------------- + """ + if center is None : + center = [0, 0] + if (options.has_key('angle')) : + angle = options['angle'] + else: + angle = 0 + if (options.has_key('extent')) : + extent = options['extent'] + else: + extent = 360 + if (options.has_key('step')) : + step = options['step'] + else: + step = 10 + pts = [] + + if (extent > 0 and step > 0) : + #A Verifier ! + alpha = angle + while(alpha <= angle+extent): + (x_n, y_n) = rad_point(center, radius, alpha) + pts.append((x_n, y_n)) + angle += step + + elif (extent < 0 and step < 0) : + #Ca me semble buggue !! + #Si extent négatif, il faut aussi que step le soit + #Si ca boucle ! + alpha = angle + while(alpha >= angle+extent): + pts.append(rad_point(center, radius, alpha)) + alpha += step + else: + raise ValueError("Step and Extent havent the same sign") + return tuple(pts) + +def rad_point(center, radius, angle): + """ + #--------------------------------------------------------------------------- + # Graphics::rad_point + # retourne le point circulaire défini par centre-rayon-angle + #--------------------------------------------------------------------------- + # paramètres : + # center : <coordonnée> coordonnée [x,y] du centre de l'arc, + # radius : <dimension> rayon de l'arc, + # angle : <angle> angle du point de circonférence avec le centre du cercle + #--------------------------------------------------------------------------- + """ + alpha = radians(angle) + + xpt = center[0] + (radius * cos(alpha)) + ypt = center[1] + (radius * sin(alpha)) + + return (xpt, ypt) + +def bezier_segment(coords, **options): + """ + #--------------------------------------------------------------------------- + # Graphics::bezier_segment + # Calcul d'une approximation de segment (Quadratique ou Cubique) de bezier + #--------------------------------------------------------------------------- + # paramètres : + # points : <[P1, C1, <C1>, P2]> liste des points définissant + # le segment de bezier + # + # options : + # -tunits : <integer> nombre pas de division des segments bezier + # (par défaut 20) + # -skipend : <boolean> : ne pas retourner le dernier point du + # segment (chainage) + #--------------------------------------------------------------------------- + """ + if (options.has_key('tunits')) : + tunits = options['tunits'] + else: + tunits = 20 + + + if options.has_key('skipend'): + skipendpt = options['skipend'] + else: + skipendpt = None + + pts = [] + + if (skipendpt) : + lastpt = tunits-1 + else: + lastpt = tunits + for i in xrange(0, lastpt+1): + if (i) : + t = (i/tunits) + else: + t = i + pts.append(bezier_point(t, coords)) + + return pts + + +def bezier_point(t, coords): + """ + #--------------------------------------------------------------------------- + # Graphics::bezier_point + # calcul d'un point du segment (Quadratique ou Cubique) de bezier + # params : + # t = <n> (représentation du temps : de 0 à 1) + # coords = (P1, C1, <C1>, P2) liste des points définissant le segment + # de bezier P1 et P2 : extémités du segment et pts situés sur la courbe + # C1 <C2> : point(s) de contrôle du segment + #--------------------------------------------------------------------------- + # courbe bezier niveau 2 sur (P1, P2, P3) + # P(t) = (1-t)²P1 + 2t(1-t)P2 + t²P3 + # + # courbe bezier niveau 3 sur (P1, P2, P3, P4) + # P(t) = (1-t)³P1 + 3t(1-t)²P2 + 3t²(1-t)P3 + t³P4 + #--------------------------------------------------------------------------- + """ + ncoords = len(coords) + if ncoords == 3: + (p1, c1, p2) = coords + c2 = None + elif ncoords == 4: + (p1, c1, c2, p2) = coords + + # extrémités : points sur la courbe + #A VERIFIER + #Pas compris + if (not t): + return tuple(p1) + if (t >= 1.0): + return p2 + + + t2 = t * t + t3 = t2 * t + pt = [] + + # calcul pour x et y + for i in (0, 1) : + + if (c2) : + r1 = (1 - (3*t) + (3*t2) - t3) * p1[i] + r2 = ((3*t) - (6*t2) + (3*t3)) * c1[i] + r3 = ((3*t2) - (3*t3)) * c2[i] + r4 = (t3) * p2[i] + + pt[i] = (r1 + r2 + r3 + r4) + + else : + r1 = (1 - (2*t) + t2) * p1[i] + r2 = ((2*t) - (2*t2)) * c1[i] + r3 = (t2) * p2[i] + + pt[i] = (r1 + r2 + r3) + + return tuple(pt) + +def bezier_compute(coords, **options): + """ + #--------------------------------------------------------------------------- + # Graphics::bezier_compute + # Retourne une liste de coordonnées décrivant un segment de bezier + #--------------------------------------------------------------------------- + # paramètres : + # coords : <coordsList> liste des points définissant le segment + # de bezier + # + # options : + # -precision : <dimension> seuil limite du calcul d'approche de la courbe + # -skipend : <boolean> : ne pas retourner le dernier point du segment + # (chaînage bezier) + #--------------------------------------------------------------------------- + """ + if (options.has_key('precision')) : + precision = options['precision'] + else: + precision = bezierClosenessThreshold + lastit = [] + + subdivide_bezier(coords, lastit, precision) + + if (not options.has_key('skipend') or not options['skipend']): + lastit.append(coords[3]) + + return lastit + +def smallenough_bezier(bezier, precision): + """ + #--------------------------------------------------------------------------- + # Graphics::smallEnought + # intégration code Stéphane Conversy : calcul points bezier + # (précision auto ajustée) + #--------------------------------------------------------------------------- + # distance is something like num/den with den=sqrt(something) + # what we want is to test that distance is smaller than precision, + # so we have distance < precision ? eq. to distance^2 < precision^2 ? + # eq. to (num^2/something) < precision^2 ? + # eq. to num^2 < precision^2*something + # be careful with huge values though (hence 'long long') + # with common values: 9add 9mul + #--------------------------------------------------------------------------- + """ + (pt_x, pt_y) = (0, 1) + (a, b) = (bezier[0], bezier[3]) + + den = ((a[pt_y]-b[pt_y])*(a[pt_y]-b[pt_y])) + ((b[pt_x]-a[pt_x])*(b[pt_x]-a[pt_x])) + p = precision*precision + + # compute distance between P1|P2 and P0|P3 + mat = bezier[1] + num1 = ((mat[pt_x]-a[pt_x])*(a[pt_y]-b[pt_y])) + ((mat[pt_y]-a[pt_y])*(b[pt_x]-a[pt_x])) + + mat = bezier[2] + num2 = ((mat[pt_x]-a[pt_x])*(a[pt_y]-b[pt_y])) + ((mat[pt_y]-a[pt_y])*(b[pt_x]-a[pt_x])) + + # take the max + num1 = max(num1, num2) + + if (p*den > (num1*num1)): + return 1 + else: + return 0 + +def subdivide_bezier(bezier, it, precision, integeropt): + """ + #--------------------------------------------------------------------------- + # Graphics::subdivide_bezier + # subdivision d'une courbe de bezier + #--------------------------------------------------------------------------- + """ + (b0, b1, b2, b3) = bezier + + if (smallenough_bezier(bezier, precision)) : + it.append((b0[0], b0[1])) + + else : + (left, right) = (None, None) + + for i in (0, 1) : + + if (integeropt) : + # int optimized (6+3=9)add + (5+3=8)shift + + left[0][i] = b0[i] + left[1][i] = (b0[i] + b1[i]) >> 1 + # keep precision + left[2][i] = (b0[i] + b2[i] + (b1[i] << 1)) >> 2 + + tmp = (b1[i] + b2[i]) + left[3][i] = (b0[i] + b3[i] + (tmp << 1) + tmp) >> 3 + + right[3][i] = b3[i] + right[2][i] = (b3[i] + b2[i]) >> 1 + # keep precision + right[1][i] = (b3[i] + b1[i] + (b2[i] << 1) ) >> 2 + right[0][i] = left[3][i] + + else : + # float + + left[0][i] = b0[i] + left[1][i] = float(b0[i] + b1[i]) / 2 + left[2][i] = float(b0[i] + (2*b1[i]) + b2[i]) / 4 + left[3][i] = float(b0[i] + (3*b1[i]) + (3*b2[i]) + b3[i]) / 8 + + right[3][i] = b3[i] + right[2][i] = float(b3[i] + b2[i]) / 2 + right[1][i] = float(b3[i] + (2*b2[i]) + b1[i]) / 4 + right[0][i] = float(b3[i] + (3*b2[i]) + (3*b1[i]) + b0[i]) / 8 + + + + subdivide_bezier(left, it, precision, integeropt) + subdivide_bezier(right, it, precision, integeropt) + + +#Local Variables: +#mode : python +#tab-width: 4 +#end: |