, respectively.
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import Line, Ellipse, Color
from kivy.clock import Clock
from kivy.core.image import Image as CoreImage
from PIL import Image, ImageDraw, ImageFont
import io
import os
import numpy as np
from kivy.lang import Builder
Builder.load_file(
os.path.join(os.path.dirname(os.path.abspath(
__file__)), 'File.kv')
);
#Avoid Form1 of being resizable
from kivy.config import Config
Config.set("graphics","resizable", False);
Config.set('graphics', 'width', '480');
Config.set('graphics', 'height', '680');
#These values are adjusted by the function
#Initialize() after Clock.schedule_once
#has been executed.
#Canvas center= (XC,YC) and width and height =(W,H);
D=2000;
VX1=-60; VY1=600; VZ1=0;
VX2=60; VY2=600; VZ2=0;
P=0.5; # Function at z=D/2
N=40; #Number of pixels for representing the function
#Arrays for filling function values
x=np.zeros(N+1);
z=np.zeros(N+1); y=np.zeros( (N+1,N+1) );
# Mesh
x1=np.zeros( (N+1,N+1) );
y1=np.zeros( (N+1,N+1) ); z1=np.zeros( (N+1,N+1) );
L=130; r0=L/5; #L=Gaussian x-z scale. r0= semi-width
XG0=0; ZG0=P*D;
Amplitude=130; #Vertical scale
for n in range (0,N+1): #Filling the x-z axes
x[n]=(n-N/2)/N*L;
z[n]=(n-N/2)/N*L;
for n in range(0,N+1): #Filling function pixels
for m in range(0,N+1):
y[n][m]=Amplitude*np.exp(- (x[n]**2
+z[m]**2)/r0**2 );
Scale_x=1; Scale_y=1; Scale_z=1;
for n in range (0,N+1):
for m in range(0,N+1):#Filling Mesh
x1[n][m]=Scale_x* x[n];
z1[n][m]=Scale_z*z[m]+ZG0;
y1[n][m]=Scale_y*y[n][m];
PointList=np.zeros( (N+1,2) );
def GraphFunction(VX,VY,VZ,Which):
global x1,y1, z1, N;
if (Which==0):
r,g,b = 200, 0, 0; #red Image
Draw=Draw1
else:
r,g,b= 0, 200, 200; #cyan image
Draw=Draw2
for n in range (0,N+1): #Horizontal Lines
for m in range (0,N+1):
Factor=(D-VZ)/(D-z1[n][m]-VZ);
xA=XC+Factor*(x1[n][m]-VX)+VX
+(P/(1-P))*VX;
yA=YC-Factor*(y1[n][m]-VY)-VY
-(P/(1-P))*VY;
PointList[m]=xA,yA;
List=tuple( map(tuple,PointList) );
Draw.line( List, fill=(r,g,b), width=2 );
for n in range (0,N+1): #Vertical Lines
for m in range (0,N+1):
Factor=(D-VZ)/(D-z1[m][n]-VZ);
xA=XC+Factor*(x1[m][n]-VX)+VX
+ (P/(1-P))*VX;
yA=YC-Factor*(y1[m][n]-VY)-VY
-(P/(1-P))*VY;
PointList[m]=xA,yA;
List=tuple( map(tuple,PointList) );
Draw.line( List, fill=(r,g,b), width=2 );
Font = ImageFont.truetype('Gargi.ttf', 40);
Draw1.text( (10,10), "3D", fill =
(255,0,0,1),font=Font);
Draw2.text( (30,10), "3D", fill =
(0,255,255,1), font=Font);
def ShowScene(B):
Array1=np.array(PilImage1);
Array2=np.array(PilImage2);
Array3=Array1 | Array2;
PilImage3=Image.fromarray(Array3);
Memory=io.BytesIO();
PilImage3.save(Memory, format="png");
Memory.seek(0);
ImagePNG=CoreImage(Memory, ext="png");
B.ids.Screen1.texture=ImagePNG.texture;
ImagePNG.remove_from_cache()
Memory.close();
PilImage3.close();
Array1=None;
Array2=None;
Array3=None;
def ClearObjects():
Draw1.rectangle( (0, 0, W-10, H-10),
fill=(60, 70, 30, 1) );
Draw2.rectangle( (0, 0, W-10, H-10),
fill=(60, 70, 30, 1) );
def RotateFunction(B, Sense):
global XG0, ZG0
if Sense==-1:
Teta=np.pi/180*(-4.0);
else:
Teta=np.pi/180*(4.0);
Cos_Teta=np.cos(Teta)
Sin_Teta=np.sin(Teta);
X0=XG0; Y0=0; Z0=ZG0 # Center of rotation
for n in range(0,N+1):
for m in range(0,N+1):
if (B.ids.Button3.state=="down" or
B.ids.Button4.state=="down"):
yP=(y1[n][m]-Y0)*Cos_Teta
+ (x1[n][m]-X0)*Sin_Teta + Y0;
xP=-(y1[n][m]-Y0)*Sin_Teta
+(x1[n][m]-X0)*Cos_Teta + X0;
y1[n][m]=yP;
x1[n][m]=xP;
if (B.ids.Button5.state=="down" or
B.ids.Button6.state=="down"):
yP=(y1[n][m]-Y0)*Cos_Teta
+ (z1[n][m]-Z0)*Sin_Teta + Y0;
zP=-(y1[n][m]-Y0)*Sin_Teta
+(z1[n][m]-Z0)*Cos_Teta + Z0;
y1[n][m]=yP;
z1[n][m]=zP;
if (B.ids.Button7.state=="down" or
B.ids.Button8.state=="down"):
xP=(x1[n][m]-X0)*Cos_Teta
+ (z1[n][m]-Z0)*Sin_Teta + X0;
zP=-(x1[n][m]-X0)*Sin_Teta
+(z1[n][m]-Z0)*Cos_Teta + Z0;
x1[n][m]=xP;
z1[n][m]=zP
;
class Form1(FloatLayout):
def __init__(Handle, **kwargs):
super(Form1, Handle).__init__(**kwargs);
Event1=Clock.schedule_once(
Handle.Initialize);
def Initialize(B, *args):
global W,H, XC,YC;
global PilImage1,PilImage2, Draw1,Draw2;
#P= Percentage of D distance
global P, Amplitude;
W,H=B.ids.Screen1.size;
XC=int (W/2)+0;
YC=int(H/2)+60;
PilImage1= Image.new('RGB', (W-10, H-10),
(60, 70, 30));
Draw1 = ImageDraw.Draw(PilImage1);
PilImage2= Image.new('RGB', (W-10, H-10),
(60, 70, 30));
Draw2 = ImageDraw.Draw(PilImage2);
Font = ImageFont.truetype('Gargi.ttf', 70);
Draw1.text( (30,200), "3D Images",
fill =(255,0,0,1), font=Font);
Draw2.text( (50,200), "3D Images",
fill =(0,255,255,1), font=Font);
ShowScene(B);
def Button1_Click(B):
global Draw1, Draw2;
ClearObjects(); # Clearing Draw1 and Draw2
GraphFunction(VX1,VY1,VZ1,0);
GraphFunction(VX2,VY2,VZ2,1);
ShowScene(B);
def Button2_Click(B):
ClearObjects(); # Clearing Draw1 and Draw2
Font = ImageFont.truetype('Gargi.ttf', 70)
Draw1.text( (30,200), "3D Images",
fill =(255,0,0,1), font=Font);
Draw2.text( (50,200), "3D Images",
fill =(0,255,255,1), font=Font);
ShowScene(B);
def Button3_Click(B):
RotateFunction(B,1);
ClearObjects(); # Clearing Draw1 and Draw2
GraphFunction(VX1,VY1,VZ1,0);
GraphFunction(VX2,VY2,VZ2,1);
ShowScene(B);
def Button4_Click(B):
RotateFunction(B,-1),
ClearObjects();
GraphFunction(VX1,VY1,VZ1,0);
GraphFunction(VX2,VY2,VZ2,1);
ShowScene(B);
def Button5_Click(B):
RotateFunction(B,-1),
ClearObjects();
GraphFunction(VX1,VY1,VZ1,0);
GraphFunction(VX2,VY2,VZ2,1);
ShowScene(B);
def Button6_Click(B):
RotateFunction(B,1),
ClearObjects();
GraphFunction(VX1,VY1,VZ1,0);
GraphFunction(VX2,VY2,VZ2,1);
ShowScene(B);
def Button7_Click(B):
RotateFunction(B,-1),
ClearObjects();
GraphFunction(VX1,VY1,VZ1,0);
GraphFunction(VX2,VY2,VZ2,1);
ShowScene(B);
def Button8_Click(B):
RotateFunction(B,1),
ClearObjects();
GraphFunction(VX1,VY1,VZ1,0);
GraphFunction(VX2,VY2,VZ2,1);
ShowScene(B);
# This is the Start Up code
.
class StartUp (App):
def build (BU):
BU.title="Form1"
return Form1();
if __name__ =="__main__":
StartUp().run();
Listing 8-5The main.py Code