#The MIT License (MIT) #PSpice to Oscad Schematic Converter #This code is written by Suryavamshi Tenneti, FOSSEE, IIT Bombay #The code is modified by Sumanto Kar and Gloria Nandihal, FOSSEE, IIT Bombay from header import * import math # In the constructors of Line, Arc, Circle and Rectangle, the input parameters shiftx and shifty have already been scaled. class Line: #Constructor of Line. npoints = 0 x = [] y = [] def __init__(self, input_stream, shiftx, shifty): #This gets called when the first character of a line is "v".This function assumes "v" and the next character(usually 0) have already been read and are NOT in the stream. t = 0 temp = input_stream.readline().strip() self.npoints = 0 self.x = [] self.y = [] while(temp!=';'): #t = temp #print('Line->',temp) t = temp.split() self.x.append(int(t[0])) #t = input_stream.read(1) self.y.append(int(t[1])) #tmp = input_stream.readline().strip() .The first line, i.e.the one that contains the 'v' temp = input_stream.readline().strip() self.x[self.npoints]*= MULT self.y[self.npoints]*= -1*MULT self.x[self.npoints]-=shiftx self.y[self.npoints]-= -1*shifty self.npoints+=1 if temp != ';': print('Error! \";\" not found\n')# The last character in the description of a line is ";" def print(self, output_stream): output_stream.write('P '+str(self.npoints)+' 0 1 0 ') for i in range(self.npoints): output_stream.write(str(self.x[i])+' '+str(self.y[i])+' ') output_stream.write('N\n') class Rectangle: ## Constructor of Rectangle. x1 = 0 y1 = 0 x2 = 0 y2 = 0 def __init__(self, input_stream, shiftx, shifty): input_line = input_stream.readline().strip() #print('Rect->',input_line) self.x1, self.y1,self.x2,self.y2 = input_line.split()[:4] # The line that contains the 'r' self.x1 = (int(self.x1) * MULT) - shiftx self.x2 = (int(self.x2) * MULT) - shiftx self.y1 = (int(self.y1) * -1 * MULT) - (-1*shifty) self.y2 = (int(self.y2) * -1 * MULT) - (-1*shifty) def print(self, output_stream): output_stream.write('S '+str(self.x1)+' '+str(self.y1)+' '+str(self.x2)+' '+str(self.y2)+' 0 1 0 N\n') class Circle: # Constructor of Circle. x = 0 y = 0 r = 0 def __init__(self, input_stream, shiftx, shifty): self.x, self.y, self.r = map(int,input_stream.readline().strip().split()) #tmp = input_stream.readline().strip() #print('Circle->','x=',self.x,'y=',self.y,'r=',self.r) self.x*= MULT self.x-= shiftx self.y*=-1*MULT self.y-=-1*shifty self.r*= MULT def print(self, output_stream): output_stream.write('C '+str(self.x)+' '+str(self.y)+' '+str(self.r)+' 0 1 0 N\n') class Arc: # Constructor of Arc. x = 0 y = 0 r = 0 sa = 0 ea = 0 x1 = 0 y1 = 0 x2 = 0 y2 = 0 ## See Line::Line(istream & in , int shiftx, int shifty) above.#From pspice library, get the 3 points that describe the arc. def __init__(self, input_stream, shiftx, shifty): # Midpoints of the arcs: xA = 0.0 yA = 0.0 xB = 0.0 yB = 0.0 xC = 0.0 yC = 0.0 xmAB = 0 xmBC = 0 ymAB = 0 ymBC = 0 input_line = input_stream.readline().strip() #print('Arc->',input_line) xA,yA,xB,yB,xC,yC = map(float, input_line.split()) #tmp = input_stream.readline().strip() yA*= -1 yB*= -1 yC*= -1 xmAB = (xA+xB)/2 # The perpendicular bisectors of any two chords of a circle meet at the centre ymAB = (yA+yB)/2 xmBC = (xC+xB)/2 ymBC = (yC+yB)/2 mperpAB = -(xB - xA)/(yB - yA)# Get x and y by solving the two lines(perpendicular bisectors) mperpBC = -(xB - xC)/(yB - yC) try: self.x = math.trunc((ymBC - ymAB - mperpBC * xmBC + mperpAB * xmAB)/(-mperpBC + mperpAB)) except ZeroDivisionError: self.x = float('inf') try: self.y = math.trunc((xmBC - xmAB + (ymAB/mperpAB) - (ymBC/mperpBC))/((1.0/mperpAB)-(1.0/mperpBC))) except ZeroDivisionError: if mperpBC == 0.0: self.y = -float('inf') else: self.y = float('inf') if not math.isinf(self.y) and not math.isinf(self.x) and not math.isnan(self.x) and not math.isnan(self.y): # Get the radius: self.r = math.trunc(((self.x-xA) * (self.x-xA) + (self.y-yA) * (self.y-yA))**0.5) else: self.r = 0 a = math.atan2(yA-self.y, xA-self.x)/math.pi*10.0*180.0 # Following code is used to decide which among A and C is the starting point(and thus determines "sa") b = math.atan2(yB-self.y, xB-self.x)/math.pi*10.0*180.0 c = math.atan2(yC-self.y, xC-self.x)/math.pi*10.0*180.0 if b < max(a,c) and b > min(a,c): #b is between a and c# print('*1') #print('*1') self.sa = math.trunc(min(a,c)) self.ea = math.trunc(max(a,c)) if b > max(a,c): #b is largest# print('*2') #print('*2') self.sa = math.trunc(max(a,c)) self.ea = math.trunc(min(a,c) + 3600.0) if b < min(a,c): #b is smallest# print('*3') #print('*3') self.sa = math.trunc(max(a,c) - 3600.0) self.ea = math.trunc(min(a,c)) flag_x_inf = False flag_y_inf = False if math.isinf(self.x) or math.isnan(self.x): #self.x = shiftx flag_x_inf = True if math.isinf(self.y) or math.isnan(self.y): #self.y = shifty flag_y_inf = True xA = self.x + self.r*math.cos(self.sa*math.pi/1800.0) yA = self.y + self.r*math.sin(self.sa*math.pi/1800.0) xC = self.x + self.r*math.cos(self.ea*math.pi/1800.0) yC = self.y + self.r*math.sin(self.ea*math.pi/1800.0) self.sa+=1 self.ea-=1 self.r*=MULT self.x1 = (xA*MULT)-shiftx self.y1 = ((yA*MULT)-(-1)*shifty) self.x2 = ((xC*MULT)-shiftx) self.y2 = ((yC*MULT)-(-1)*shifty) if not flag_x_inf: self.x*=MULT self.x-=shiftx else: self.x = shiftx if not flag_y_inf: self.y*=MULT self.y-=(-1)*shifty else: self.y = shifty # scale and shift: #startx, starty, endx, endy are redundant.May not even be in use.Haven 't been fixed. if math.isinf(self.x1) or math.isnan(self.x1) or math.isinf(self.y1) or math.isnan(self.y1) or math.isinf(self.x2) or math.isnan(self.x2) or math.isinf(self.y2) or math.isnan(self.y2): self.x1 = -(2**31) self.x2 = -(2**31) self.y1 = -(2**31) self.y2 = -(2**31) else: self.x1 = math.trunc(self.x1) self.y1 = math.trunc(self.y1) self.x2 = math.trunc(self.x2) self.y2 = math.trunc(self.y2) ''' if mperpAB == 0 or mperpBC == 0: print('mperpAB=',mperpAB, 'mperpBC=', mperpBC) print('X=',self.x,'Y=',self.y) print('Radius=',self.r) print('a=',a,'b=',b,'c=',c) print('xA=',xA,'yA=',yA,'xC=',xC,'yC=',yC) print('x=',self.x,'y=',self.y) print('x1=',self.x1,'x2=',self.x2,'y1=',self.y1,'y2=',self.y2) print('sa=',self.sa,'ea=',self.ea) ''' def print(self,output_stream): output_stream.write('A '+str(math.trunc(self.x))+' '+str(math.trunc(self.y))+' '+str(int(self.r))+' '+str(int(self.sa))+' '+str(int(self.ea))+' '+' 0 1 0 N '+str(int(self.x1))+' '+str(int(self.y1))+' '+str(int(self.x2))+' '+str(int(self.y2))+' '+'\n') class Text: #Constructor of Circle. x = 0 y = 0 text = '' orient = '' def __init__(self,input_stream, shiftx, shifty): input_line = input_stream.readline().strip().split() self.x,self.y,self.orient = input_line[:3] self.x = int(self.x) self.y = int(self.y) #tmp = input_stream.readline().strip() self.text = input_stream.readline().strip() self.x*=MULT self.y*=-1*MULT self.x-=shiftx self.y-=-1*shifty def print(self,output_stream): output_stream.write('T ') # The line that contains the 't' if self.orient[0] == 'h': output_stream.write('0 ') elif self.orient[0] == 'v': output_stream.write('900 ') output_stream.write(str(self.x)+' '+str(self.y)+' '+str(30)+' 0 0 0 '+self.text+'\n') class Design: #Constructor of Design. shiftx = 0 shifty = 0 lines = [] rects = [] circles = [] arcs = [] texts = [] # Reads the whole design, makes Line, Circle, etc.objects and stores them in the appropriate container(appropriate vector) def __init__(self, input_stream): g = 0 tmp = '' t = 0 tint = '' tmp = input_stream.readline().strip() #print('Design->', tmp) if('@graphics' not in tmp): print('Design not found!') return #print('Graphics->',tmp.split()) self.lines = [] self.rects = [] self.circles = [] self.arcs = [] self.texts = [] tmp = tmp.split() tint,tint,tint,self.shiftx,self.shifty= map(str,tmp[:5]) if len(tmp) > 5: tmp = ''.join(tmp[5:]) self.shiftx = int(self.shiftx)*MULT # print('shiftx->', self.shiftx, 'shifty->', self.shifty) self.shifty = int(self.shifty)*MULT #print('shiftx->',self.shiftx,'shifty->',self.shifty) while(t!= '*'): #As long as we haven 't reached the description of the next Component continue reading the lib file. g = input_stream.tell() # Get the position of the read head, so that we can go back to this position t = input_stream.read(1) # Get the first character of the description, store in "t".This character gives what shape it is. if not t: break if t == 'v': #print('Line') input_stream.read(1) input_stream.read(1) input_stream.read(1) l = Line(input_stream, self.shiftx, self.shifty) self.lines.append(l) elif t == 'r': #print('Rect') input_stream.read(1) input_stream.read(1) input_stream.read(1) r = Rectangle(input_stream, self.shiftx, self.shifty) self.rects.append(r) elif t == 'c': #print('Circle') input_stream.read(1) input_stream.read(1) input_stream.read(1) c = Circle(input_stream, self.shiftx, self.shifty) self.circles.append(c) elif t == 'a': #print('Arc') input_stream.read(1) input_stream.read(1) input_stream.read(1) a = Arc(input_stream, self.shiftx, self.shifty) self.arcs.append(a) elif t == 'z': #print('Text') input_stream.read(1) input_stream.read(1) input_stream.read(1) z = Text(input_stream, self.shiftx, self.shifty) self.texts.append(z) else: #If t is neither 'v', 'r', 'c' tmp = input_stream.readline().strip() g = input_stream.tell() input_stream.seek(g) def print(self, output_stream): for i in range(len(self.lines)): self.lines[i].print(output_stream) for i in range(len(self.rects)): self.rects[i].print(output_stream) for i in range(len(self.circles)): self.circles[i].print(output_stream) for i in range(len(self.arcs)): self.arcs[i].print(output_stream) for i in range(len(self.texts)): self.texts[i].print(output_stream)