Skip to content

Commit ed32856

Browse files
committed
README.md added
- Readme created but it needs to be finished - Interface updated - Bugs fixed
1 parent 94ab87e commit ed32856

File tree

3 files changed

+74
-15
lines changed

3 files changed

+74
-15
lines changed

.pylintrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
extension-pkg-whitelist=PyQt5

README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Linear transformation visualization in 3D
2+
3+
## Why?
4+
5+
A linear transformation is a function from one vector space to another that respects the linear structure of each vector space ([Learn more](https://brilliant.org/wiki/linear-transformations/)). For visualizing this we can transform a vector as we can see in the Fig. 1.
6+
7+
<figure>
8+
<img src="vector_linearTransformation.png" alt="vector transformed" style="width:40%;
9+
display: block;
10+
margin-left: auto;
11+
margin-right: auto;">
12+
<figcaption style="text-align: center;">Fig.1 - Vector transformed with a transformation matrix</figcaption>
13+
</figure>
14+
15+
But it has an obvious problem, because the linear transformation transform the whole space, not just the vector, in other words it transforms the basis vectors thus every vector in the space gets transformed too. That's why i created this app so everyone can see how a transformation matrix change the whole space.
16+
17+
## Installation guide
18+
19+
### With the executable file
20+
21+
1. Install Python from the [python web](https://www.python.org/).
22+
2. Download the executable file for your OS (Linux or Windows).
23+
3. Execute the file.
24+
4. Start using.
25+
26+
The executable was created with [PyInstaller](http://www.pyinstaller.org/).
27+
28+
### Manual installation
29+
30+
1. Install Python from the [python web](https://www.python.org/).
31+
2. Install pip from the [pip web](https://pip.pypa.io/en/stable/installing/)
32+
3. Install the dependences using pip.
33+
- pip install sympy
34+
- pip install pyqt5
35+
- pip install numpy
36+
4. Download the main.py, Plotting.py and Matrix.py files.
37+
5. In the console go to the files location
38+
6. Run the main file with <code>python3.8 main.py</code>
39+
40+
## How to use
41+

main.py

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from numpy import linspace,column_stack,array #For create the linspace for the plotting
1010

1111
import PyQt5.QtWidgets as QtWidgets #Python GUI
12+
from PyQt5.QtGui import QFont #Pyqt5 fonts
1213

1314
from Plotting import PlotWidget #The plot object
1415

@@ -25,11 +26,10 @@ def colorizer(x, y,z):
2526
2627
"""
2728
r = min(1, 1-y/3)
28-
g = min(1, 1+y/3)
29+
g = min(1, 1+x/3)
2930
b = 1/4 + x/16
3031
return (r, g, b)
3132

32-
3333
def get_grid(min,max):
3434
"""Return a grid in x, y and z
3535
@@ -75,44 +75,55 @@ def adjust_plot(axes):
7575
axes.set_ylabel('y') # Axes names
7676
axes.set_zlabel('z') #
7777
axes.grid(True) # Don't show the grid
78-
axes.view_init(10,5) # View init at 15 and 5 degrees
7978

8079
def exceptionDialog(msg):
8180
dlg = QtWidgets.QErrorMessage()
8281
dlg.showMessage(msg)
8382
dlg.exec_()
8483

85-
8684
def transformAndPlot(plot,matrix):
85+
8786
try:
8887
matrix = array(matrix)
8988
print(matrix)
9089
interface.setMatrix(matrix)
9190
xyzgrid = get_transformedGrid(originalGrid, Matrix([[N(matrix[0,0]),N(matrix[0,1]),N(matrix[0,2])],
9291
[N(matrix[1,0]),N(matrix[1,1]),N(matrix[1,2])],
9392
[N(matrix[2,0]),N(matrix[2,1]),N(matrix[2,2])]])) # get a transformed grid
94-
9593
plot.scatter(xyzgrid,colors)
9694
adjust_plot(plot.axes)
9795
plot.fig.canvas.draw()
9896
plot.fig.canvas.flush_events()
99-
except ValueError as err:
100-
print(err)
101-
exceptionDialog('An error has ocurred. Remember that you only can write operations between numbers or trigonometric functions in the matrix boxes. ex. sin(3*pi/2) or 30+0.5')
97+
except:
98+
exceptionDialog('An error has ocurred. Remember that you only can write operations between numbers or trigonometric functions in the matrix boxes. ex. sin(3*pi/2) or sqrt(2)/2+5')
10299

103100
def examplesComboBox(window,comboBox):
104101
examples = {
105102
'Original Grid' :[[1, 0, 0],[0, 1, 0],[0, 0, 1]],
103+
'Personalized matrix' :[[1, 0, 0],[0, 1, 0],[0, 0, 1]],
104+
'Reflect in X' :[[-1, 0, 0],[0, 1, 0],[0, 0, 1]],
105+
'Reflect in Y' :[[1, 0, 0],[0, -1, 0],[0, 0, 1]],
106+
'Reflect in Z' :[[1, 0, 0],[0, 1, 0],[0, 0, -1]],
107+
'Stretch in Y' :[[1, 0, 0],[0, 2, 0],[0, 0, 1]],
108+
'Compact in Y' :[[1, 0, 0],[0, '1/2', 0],[0, 0, 1]],
106109
'X rotation 45º' :[[1, 0, 0],[0, 'cos(45*pi/180)', '-sin(45*pi/180)'],[0, 'sin(45*pi/180)', 'cos(45*pi/180)']],
107110
'Y rotation 45º' :[['cos(45*pi/180)', '-sin(45*pi/180)', 0],['sin(45*pi/180)', 'cos(45*pi/180)', 0],[0, 0, 1]],
108-
'Z rotation 45º' :[['cos(45*pi/180)', 0, '-sin(45*pi/180)'],[0, 1, 0],['sin(45*pi/180)', 0, 'cos(45*pi/180)']]
111+
'Z rotation 45º' :[['cos(45*pi/180)', 0, '-sin(45*pi/180)'],[0, 1, 0],['sin(45*pi/180)', 0, 'cos(45*pi/180)']],
112+
'X-Y rotation 45º-10º':[['cos(45*pi/180)*cos(10*pi/180)','cos(45*pi/180)*sin(10*pi/180)-sin(45*pi/180)','cos(45*pi/180)*sin(10*pi/180)+sin(45*pi/180)*sin(10*pi/180)'],['sin(45*pi/180)*cos(10*pi/180)','sin(45*pi/180)*sin(10*pi/180)+cos(45*pi/180)','sin(45*pi/180)*sin(10*pi/180)-cos(45*pi/180)'],['-sin(10*pi/180)','cos(10*pi/180)','cos(10*pi/180)']],
113+
'Only XY dimension' :[[1, 0, 0],[0, 1, 0],[0, 0, 0]],
114+
'Only YZ dimension' :[[0, 0, 0],[0, 1, 0],[0, 0, 1]],
115+
'Only XZ dimension' :[[1, 0, 0],[0, 0, 0],[0, 0, 1]]
109116
}
110117
for key in examples:
111118
examplesWidget.addItem(key)
112119

113120
examplesWidget.activated[str].connect(lambda str: transformAndPlot(window,examples.get(str)))
114121

115-
window.addToLayout(examplesWidget, [11,1],[3,1])
122+
window.addToLayout(examplesWidget, [13,2],[3,1])
123+
124+
def plotButton(plot,matrix):
125+
transformAndPlot(plot,matrix)
126+
examplesWidget.setCurrentIndex(1)
116127

117128
if __name__ == "__main__":
118129
"""Transformation matrix"""
@@ -131,20 +142,26 @@ def examplesComboBox(window,comboBox):
131142
plot.scatter(xyzgrid,colors) # Scatter
132143

133144
adjust_plot(plot.axes) # Set the limits of the axes
145+
plot.axes.view_init(10,5) # View init at 15 and 5 degrees
134146

135-
plot.addToLayout(QtWidgets.QLabel('Examples'),[11,0],[1,1])
147+
examples_label = QtWidgets.QLabel('Examples')
148+
examples_label.setFont(QFont('Sans Serif', 20))
149+
plot.addToLayout(examples_label,[12,2],[1,1])
136150
examplesWidget = QtWidgets.QComboBox()
137151
examplesComboBox(plot,examplesWidget)
138152

153+
matrix_label = QtWidgets.QLabel('Transformation Matrix')
154+
matrix_label.setFont(QFont('Sans Serif', 20))
155+
plot.addToLayout(matrix_label,[12,4],[2,1])
139156
interface = MatrixButtons() # Get the interface
140-
plot.addToLayout(interface,[11,4],[10,2]) # add the interface to the plot layout
157+
plot.addToLayout(interface,[11,5],[10,2]) # add the interface to the plot layout
141158

142159
interface.setMatrix(array(transformationMatrix))
143160

144161
interface.plotButton.clicked.connect(
145-
lambda: transformAndPlot(plot,[[interface.matrix00.text(), interface.matrix10.text(), interface.matrix20.text()],
146-
[interface.matrix01.text(), interface.matrix11.text(), interface.matrix21.text()],
147-
[interface.matrix02.text(), interface.matrix12.text(), interface.matrix22.text()]]))
162+
lambda: plotButton(plot,[[interface.matrix00.text(), interface.matrix10.text(), interface.matrix20.text()],
163+
[interface.matrix01.text(), interface.matrix11.text(), interface.matrix21.text()],
164+
[interface.matrix02.text(), interface.matrix12.text(), interface.matrix22.text()]]))
148165

149166
plot.show()
150167
app.exec()

0 commit comments

Comments
 (0)