Toutes les versions de cet article : [English] [français]
Since version 7.9.1, MathGraph32 allows the creation of figures using Python language.
The figure below creates five free points A, B, C , D and E defining a five sides polygon then calls in an iterative way the function intSeg.
If you change the Python code below, click on button Execute under the edition text area input.
You will find at the bottom of this page the HTML code allowing to dsipaly it in a web page.
To work properly, this figure needs a frame (set of axis). This frame is provided by the fig parameter of the HTML tag
To get the following bounces, use button + and - at the bottom right corner of the figure (these buttons increment or decrement variable p (maxi value of p : 50)
To be noted : this figure is dynamic (you can capture points A, B, C, C, E, M and N).
The points A, B, C, D and E are free points. Their initial coordinates are set lines 83 to 87.
If you want these points to be fixed, replace these five lines by the following ones (choose the coordinates as you want) :
A = addPointXY(-10, 8, 'A')
B = addPointXY(10, 8, 'B')
C = addPointXY(10, -8, 'C')
D = addPointXY(0, -2, 'D')
E = addPointXY(-10, -8, 'E')
Please notice that, once the Python code executed, clicking on the Download button will allow you to save the generated figure in a mgj file. Then you will be able to open this file with MathGraph32.
Using Protocol tool you will see that this figure is made of more than 3000 objects, some of them beeing matrices. Yet this figure is fluid !
Voici le code html qui a permis de mettre cette figure en ligne :
<script type = "text/mtgPython" id = "PythonCodeId">
# Function looking for the intersection of the with pt as origine and directed by a vector of coordinates (a, b) with the sides of the polygon
# where {a} ans {b} are two real calculations of the figure
# Retunrs an array type of [ptret, u, v] where ptret is the nearest intersection point with the polygon sides and u and v two real calculations
# containing the coordinates of an "after bounce" vector
def intSeg(pt, a, b, ind):
# We calculate pt coordinates
addXMeasure(pt, f'xpt{ind}')
addYMeasure(pt, f'ypt{ind}')
trans = addTranslationxy(a, b)
ptim = addPointIm(pt, trans)
setHidden(ptim)
ray = addRay(pt, ptim)
setHidden(ray)
size = len(tabPt) - 1 # -1 because the last point of the array is the same as the first one
# To know if pt is on one of the polygone sides we create abscissa measures of pt relatively the the polygone vertexes
# and we create existence tests of these measures
tabMesAbs = []
tabTestMesAbs = []
tabTestAbs = []
for i in range(size):
absMes = addAbsMeasure(pt, tabPt[i], tabPt[i + 1], f'mesAbs{ind}{i}')
tabMesAbs.append(absMes)
tabTestMesAbs.append(addTest(absMes, f'testMesAbs{ind}{i}'))
# Tests underneath value will be1 if the abscissa exists and has a value between 0 and 1 and 0 else
tabTestAbs.append(addCalc(f'testAbs{ind}{i}', f'si(testMesAbs{ind}{i},mesAbs{ind}{i}>=0&mesAbs{ind}{i}<=1,0)'))
# We create an array containing the intersect points of the ray with each side of the polygon
tabInt = []
for i in range(size):
point = addIntLineLine(ray, tabSeg[i])
tabInt.append(point)
setHidden(point)
# We create an array containing the abscissas of the intersection points
tabAbs = []
for i in range(size):
tabAbs.append(addXMeasure(tabInt[i],f'xint{ind}{i}'))
# We create an array containing the ordinates of the intersection points
tabOrd = []
for i in range(size):
tabOrd.append(addYMeasure(tabInt[i],f'yint{ind}{i}'))
# We create an arrray containing the existence tests of the abscissas to know if these abscissas exist
tabTest = []
for i in range(size):
tabTest.append(addTest(tabAbs[i], f'test{ind}{i}'))
# We will create a five columns matrix. The first column will contain the square of the distances between pt
# and the intersection points of the ray with the polygone sides with the condition that pt is not on the side
# the second and third column will contain the coordinates of the intersection point
# the fourth and fifth columns will contain the coordinates of the first vertex of the matching polygon side
mat = []
matvalid = []
for i in range(size):
matvalid.append(f'test{ind}{i}&(1-testAbs{ind}{i})')
lig = [f'si(matvalid{ind}(1,{i}+1),(xint{ind}{i}-xpt{ind})^2+(yint{ind}{i}-ypt{ind})^2,10^99)', f'si(matvalid{ind}(1,{i}+1),xint{ind}{i},0)', f'si(matvalid{ind}(1,{i}+1),yint{ind}{i},0)', f'matAbs(1,{i} + 1)', f'matOrd(1,{i} + 1)']
mat.append(lig)
# Matrix V is a row matrix of for instance 5 cells if the polygon has 5 vertices
# Each cell of this matrix contains 1 if the ray intersects with the segment and point pt is not on the segment and 0 otherwise
V = addMatrix(f'matvalid{ind}', [matvalid])
# The following calculation will contain formula 1/0 if none of the intersection points between the ray and the segments is valid and 1 otherwise
addCalc(f'valid{ind}', f'si(somme(matvalid{ind}(1,k), k, 1, {size}, 1)>0,1, 1/0)')
A = addMatrix(f'A{ind}',mat)
# Matrix B will contain the rows of matrix A sorted by it' first column (increasing sort order)
B = addCalcMat(f'B{ind}', f'sortbycol(A{ind}, 1)')
xptret = addCalc(f'xptret{ind}', f'B{ind}(1,2)*valid{ind}') # This calculation will not exist if no intersection point between the ray and the segment is valid
yptret = addCalc(f'yptret{ind}', f'B{ind}(1,3)')
ptret = addPointXY(xptret, yptret) # The intersection between the ray and the segment that is the nearest to point pt
addVector(pt,ptret, 'red')
extrem = addPointXY(f'B{ind}(1,4)', f'B{ind}(1,5)') #extrem is a point coordinates of which are the coordinates of a vertex of the segment the ray intersects with
setHidden(extrem)
seg = addSegment(extrem, ptret) # segment starting from the intersect point and ending to one of the vertices of the sgement the ray intersects with
setHidden(seg)
perp = addLinePerp(ptret, seg) #perpendicualr to the segment going trough the intersection point
setHidden(perp)
ptsym = addImPointSymAx(pt, perp) #Symmetric point of point pt relative to this perpendicular line
setHidden(ptsym)
xptsym = addXMeasure(ptsym, f'xptsym{ind}')
yptsym = addYMeasure(ptsym, f'yptsym{ind}')
xret = addCalc(f'xret{ind}', f'xptsym{ind}-xptret{ind}')
yret = addCalc(f'yret{ind}', f'yptsym{ind}-yptret{ind}')
# We return an array. The first element is the intersection point with one of the five segments. The second and third element are the coordinates of the vector giving the direction after the bounce.
return [ptret, xret, yret]
p = addVariable('p', 12, 0, 50, 1, True)
O = getPointByName('O') # L'origine du repère
A = addFreePoint(-10, 8, 'A')
B = addFreePoint(10, 8, 'B')
C = addFreePoint(10, -8, 'C')
D = addFreePoint(0, -2, 'D')
E = addFreePoint(-10, -8, 'E')
setPointNameOffset(A, -15, - 20)
setPointNameOffset(B, 5, - 20)
tabPt = [A, B, C, D, E]
# On referme le tableau de points
tabPt += [A]
tabSeg = []
tabAbs = []
tabOrd = []
for i in range(len(tabPt) - 1):
pt1 = tabPt[i]
pt2 = tabPt[i + 1]
tabAbs.append(addXMeasure(pt1, f'x{i}'))
tabOrd.append(addYMeasure(pt1, f'y{i}'))
tabSeg.append(addSegment(pt1, pt2))
# On crée deux matrices contenant les abscisses pour l'une et les ordonnées pour l'autre
addMatrix('matAbs', [tabAbs])
addMatrix('matOrd', [tabOrd])
pol = addPolygon(tabPt)
surf = addSurface(pol, 'green')
setHidden(pol)
M = addFreePoint(-7, -2, 'M', 'blue', 'X')
N = addFreePoint(-5, 4, 'N')
xM = addXMeasure(M, 'xM')
yM = addYMeasure(M, 'yM')
xN = addXMeasure(N, 'xN')
yN = addYMeasure(N, 'yN')
a = addCalc('a', 'xN-xM')
b = addCalc('b', 'yN-yM') # Le vecteur de coordonnées (a; b) donne la direction de la demi-droite [M,N)
point = M
x = a
y = b
for i in range(50):
# On crée un point image par l'homothétie de centre O et rapport 1/(i<=p). Quand i > p , le test (i<=p) renvoie comme valeur 0
# et le quotient 1/'i<=p) n'existe pas. Ainsi le point et les suivants n'existeront pas pour i > p
# On peut changer la valeur de p en cliquant sur les boutons + et - associés à la variable p en bas et à droite.
pointIm = addImPointDilation(point, O, f'1/({i}<=p)', f'N{i}')
setHidden(pointIm)
[point, x, y] = intSeg(pointIm, x, y, i)
</script>
<script async src="https://www.mathgraph32.org/js/mtgLoad/mathgraphElements.js"></script>
<mathgraph-player width="800" height="600" python-code-id="PythonCodeId" fig = "TWF0aEdyYXBoSmF2YTEuMAAAABUAAmZy####AQD#AQAAAAAAAAAABQUAAALHAAABAQAAAAAAAAABAAAANf####8AAAABAApDQ2FsY0NvbnN0AP####8AAnBpABYzLjE0MTU5MjY1MzU4OTc5MzIzODQ2#####wAAAAEACkNDb25zdGFudGVACSH7VEQtGP####8AAAABAApDUG9pbnRCYXNlAP####8AAAAAP4AAAAAOAAFPAMAoAAAAAAAAAAAAAAAAAAAAAAUAAUB5AAAAAAAAQHLKPXCj1wr#####AAAAAQAUQ0Ryb2l0ZURpcmVjdGlvbkZpeGUA#####wEAAAA#gAAAAA4AAAEAAAABAAAAAQE#8AAAAAAAAP####8AAAABAA9DUG9pbnRMaWVEcm9pdGUA#####wAAAAA#gAAAAQ4AAUkAwBgAAAAAAAAAAAAAAAAAAAAABQABQD0AAAAAAAAAAAAC#####wAAAAEACUNEcm9pdGVBQgD#####AAAAAD+AAAAAEAAAAQAAAAEAAAABAAAAA#####8AAAABABZDRHJvaXRlUGVycGVuZGljdWxhaXJlAP####8AAAAAP4AAAAAOAAABAAAAAQAAAAEAAAAE#####wAAAAEACUNDZXJjbGVPQQD#####AQAAAD+AAAAAAAABAAAAAQAAAAP#####AAAAAQAQQ0ludERyb2l0ZUNlcmNsZQD#####AAAABQAAAAb#####AAAAAQAQQ1BvaW50TGllQmlwb2ludAD#####AQAAAD+AAAAADgAAAQAABQABAAAABwAAAAkA#####wAAAAA#gAAAAQ4AAUoAwCgAAAAAAADAEAAAAAAAAAAABQACAAAAB#####8AAAACAAdDUmVwZXJlAP####8A5ubmP4AAAAADcmVwAAEAAAABAAAAAwAAAAkBAQAAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAABP#AAAAAAAAAAAAABP#AAAAAAAAD#####AAAAAQAKQ1VuaXRleFJlcAD#####AAR1bml0AAAACv####8AAAABAAtDSG9tb3RoZXRpZQD#####AAAAAf####8AAAABAApDT3BlcmF0aW9uAwAAAAE#8AAAAAAAAP####8AAAABAA9DUmVzdWx0YXRWYWxldXIAAAAL#####wAAAAEAC0NQb2ludEltYWdlAP####8BAAAAP4AAAAAQAAJXIgEAAAEAAAAAAwAAAAz#####AAAAAQAJQ0xvbmd1ZXVyAP####8AAAABAAAADf####8AAAABAAdDQ2FsY3VsAP####8AB25iZ3JhZHgAAjIwAAAAAUA0AAAAAAAAAAAAEQD#####AAduYmdyYWR5AAIyMAAAAAFANAAAAAAAAP####8AAAABABRDSW1wbGVtZW50YXRpb25Qcm90bwD#####ABRHcmFkdWF0aW9uQXhlc1JlcGVyZQAAABsAAAAIAAAAAwAAAAoAAAAPAAAAEP####8AAAABABNDQWJzY2lzc2VPcmlnaW5lUmVwAAAAABEABWFic29yAAAACv####8AAAABABNDT3Jkb25uZWVPcmlnaW5lUmVwAAAAABEABW9yZG9yAAAACgAAAAsAAAAAEQAGdW5pdGV4AAAACv####8AAAABAApDVW5pdGV5UmVwAAAAABEABnVuaXRleQAAAAr#####AAAAAQAQQ1BvaW50RGFuc1JlcGVyZQAAAAARAAAAAD+AAAAADgAAAQAABQAAAAAKAAAADgAAABIAAAAOAAAAEwAAABYAAAAAEQAAAAA#gAAAAA4AAAEAAAUAAAAACgAAAA0AAAAADgAAABIAAAAOAAAAFAAAAA4AAAATAAAAFgAAAAARAAAAAD+AAAAADgAAAQAABQAAAAAKAAAADgAAABIAAAANAAAAAA4AAAATAAAADgAAABUAAAAMAAAAABEAAAAWAAAADgAAAA8AAAAPAAAAABEAAAAAP4AAAAAOAAABAAAFAAAAABcAAAAZAAAADAAAAAARAAAAFgAAAA4AAAAQAAAADwAAAAARAAAAAD+AAAAADgAAAQAABQAAAAAYAAAAG#####8AAAABAAhDU2VnbWVudAAAAAARAQAAAD+AAAAAEAAAAQAAAAEAAAAXAAAAGgAAABcAAAAAEQEAAAA#gAAAABAAAAEAAAABAAAAGAAAABwAAAAEAAAAABEBAAAAP4AAAAALAAFXAMAUAAAAAAAAwDQAAAAAAAAAAAUAAT#cVniavN8OAAAAHf####8AAAACAAhDTWVzdXJlWAAAAAARAAZ4Q29vcmQAAAAKAAAAHwAAABEAAAAAEQAFYWJzdzEABnhDb29yZAAAAA4AAAAg#####wAAAAIAEkNMaWV1T2JqZXRQYXJQdExpZQEAAAARAGZmZj+AAAAAAAAAAB8AAAAOAAAADwAAAB8AAAACAAAAHwAAAB8AAAARAAAAABEABWFic3cyAA0yKmFic29yLWFic3cxAAAADQEAAAANAgAAAAFAAAAAAAAAAAAAAA4AAAASAAAADgAAACEAAAAWAAAAABEBAAAAP4AAAAALAAABAAAFAAAAAAoAAAAOAAAAIwAAAA4AAAATAAAAGQEAAAARAGZmZj+AAAAAAAAAACQAAAAOAAAADwAAAB8AAAAFAAAAHwAAACAAAAAhAAAAIwAAACQAAAAEAAAAABEBAAAAP4AAAAALAAFSAEAgAAAAAAAAwCAAAAAAAAAAAAUAAT#RG06BtOgfAAAAHv####8AAAACAAhDTWVzdXJlWQAAAAARAAZ5Q29vcmQAAAAKAAAAJgAAABEAAAAAEQAFb3JkcjEABnlDb29yZAAAAA4AAAAnAAAAGQEAAAARAGZmZj+AAAAAAAAAACYAAAAOAAAAEAAAACYAAAACAAAAJgAAACYAAAARAAAAABEABW9yZHIyAA0yKm9yZG9yLW9yZHIxAAAADQEAAAANAgAAAAFAAAAAAAAAAAAAAA4AAAATAAAADgAAACgAAAAWAAAAABEBAAAAP4AAAAALAAABAAAFAAAAAAoAAAAOAAAAEgAAAA4AAAAqAAAAGQEAAAARAGZmZj+AAAAAAAAAACsAAAAOAAAAEAAAACYAAAAFAAAAJgAAACcAAAAoAAAAKgAAACv#####AAAAAgAMQ0NvbW1lbnRhaXJlAAAAABEBZmZmP4AAAAAAAAAAAAAAAEAYAAAAAAAAAAAAAAAfCwAB####AAAAAQAAAAAAAAABAAAAAAAAAAAAAAsjVmFsKGFic3cxKQAAABkBAAAAEQBmZmY#gAAAAAAAAAAtAAAADgAAAA8AAAAfAAAABAAAAB8AAAAgAAAAIQAAAC0AAAAbAAAAABEBZmZmP4AAAAAAAAAAAAAAAEAYAAAAAAAAAAAAAAAkCwAB####AAAAAQAAAAAAAAABAAAAAAAAAAAAAAsjVmFsKGFic3cyKQAAABkBAAAAEQBmZmY#gAAAAAAAAAAvAAAADgAAAA8AAAAfAAAABgAAAB8AAAAgAAAAIQAAACMAAAAkAAAALwAAABsAAAAAEQFmZmY#gAAAAMAgAAAAAAAAP#AAAAAAAAAAAAAAACYLAAH###8AAAACAAAAAQAAAAEAAAAAAAAAAAAACyNWYWwob3JkcjEpAAAAGQEAAAARAGZmZj+AAAAAAAAAADEAAAAOAAAAEAAAACYAAAAEAAAAJgAAACcAAAAoAAAAMQAAABsAAAAAEQFmZmY#gAAAAMAcAAAAAAAAAAAAAAAAAAAAAAAAACsLAAH###8AAAACAAAAAQAAAAEAAAAAAAAAAAAACyNWYWwob3JkcjIpAAAAGQEAAAARAGZmZj+AAAAAAAAAADMAAAAOAAAAEAAAACYAAAAGAAAAJgAAACcAAAAoAAAAKgAAACsAAAAzAAAADv##########" >
</mathgraph-player>