from ...constants import RAD2DEG, DEG2RAD
from ... import settings
import math
import numpy
from ..shape import gds_dynamic_shape, gds_shape
from ..shape_info import distance, angle_rad
from ..size_info import gds_size_info

from ...properties.predefined import number_property, bool_property, int_property, angle_property, normalized_angle_property, RESTRICT_NONNEGATIVE, angle_property, length_property, zero_length_property
from ...properties.descriptor import locked_property
from ...properties.restrictions import restrict_range
from ..coord import coord2, coord2_property, size2_property

__all__ = ["shape_arc",
	   "shape_bend",
	   "shape_bend_rel",
	   "shape_circle",
	   "shape_cross",
	   "shape_dodecagon",
	   "shape_ellipse",
	   "shape_ellipse_arc",
	   "shape_hexagon",
	   "shape_parabolic",
	   "shape_radial_wedge",
	   "shape_rect",
	   "shape_regular_polygon",
	   "shape_ring_segment",
	   "shape_round_rect",
	   "shape_round_rect_arc",
	   "shape_wedge"]

#----------------------------------------------------------------------------
# ellipses, circles and arcs
#----------------------------------------------------------------------------

class shape_ellipse_arc(gds_dynamic_shape):
	""" ellipse arc around a given center """
	center = coord2_property(default = (0.0, 0.0))
	box_size = size2_property(default = (1.0, 1.0))
	start_angle = angle_property(default = 0.0)
	end_angle = angle_property(default = 90.0)
	angle_step = angle_property(default = 1.0)
	clockwise = bool_property(default = False)
	def __init__(self,
				 center = (0.0, 0.0),
				 box_size = (1.0, 1.0),
				 start_angle=0.0,
				 end_angle = 90.0,
				 angle_step = None,
				 clockwise = False, 
				 **kwargs):
		if angle_step == None:
			angle_step = settings.get_angle_step()
		super(shape_ellipse_arc, self).__init__(
			center = center,
			box_size = box_size,
			start_angle = start_angle,
			end_angle = end_angle,
			angle_step = angle_step,
			clockwise = clockwise,
			**kwargs)

	def __calc__(self):
		sa = self.start_angle * DEG2RAD
		ea = self.end_angle * DEG2RAD 
		h_radius = self.box_size[0]/2.0
		v_radius = self.box_size[1]/2.0
		n_s = float(self.end_angle-self.start_angle)/self.angle_step
		n_steps = int(math.ceil(abs(n_s))) * numpy.sign(n_s)
		if n_steps == 0: 
			if sa == ea:
				self.__points__ = numpy.array([[math.cos(sa) * h_radius + self.center[0], math.sin(sa) * v_radius+ self.center[1]]
						 ])
			else:		
				self.__points__ = numpy.array([[math.cos(sa) * h_radius+ self.center[0], math.sin(sa) * v_radius+ self.center[1]],
						 [math.cos(ea) * h_radius+ self.center[0], math.sin(ea) * v_radius+ self.center[1]]
						 ])
			return
		
		angle_step = float(ea-sa) / n_steps
		if self.clockwise:
			angle_step = -angle_step
			sign = -1
		else:
			sign = +1
		while sign * sa > sign * ea:
			ea += sign * 2 * math.pi
	
			
		angles = numpy.arange(sa, ea + 0.5*angle_step, angle_step)
		self.__points__ = numpy.column_stack((numpy.cos(angles), numpy.sin(angles))) * numpy.array([(h_radius, v_radius)]) + numpy.array([(self.center[0], self.center[1])])

	def move(self, position):
		self.center =  (self.center.x + position[0], self.center.y + position[1])
		return self
	
	def is_empty(self):
		return self.start_angle == self.end_angle or self.box_size[0] == 0.0 or self.box_size[1] == 0.0
		

class shape_arc(shape_ellipse_arc):
	""" circular arc """
	radius = length_property(default = 1.0)
	box_size = locked_property()
	
	def __init__(self,
				 center = (0.0, 0.0),
				 radius = 1.0,
				 start_angle=0.0,
				 end_angle = 90.0,
				 angle_step = None,
				 clockwise = False,
				 **kwargs):
		super(shape_arc, self).__init__(
			center = center,
			radius = radius,
			start_angle = start_angle,
			end_angle = end_angle,
			angle_step = angle_step,
			clockwise = clockwise,
			**kwargs)

	def __calc__(self):
		self.box_size = coord2(2*self.radius, 2*self.radius)
		shape_ellipse_arc.__calc__(self)

class shape_bend(shape_arc):
	""" bend: circular arc but specified by its starting point insetad of center """
	start_point = coord2_property(default = (0.0, 0.0))
	center = locked_property()
	start_angle = locked_property()
	end_angle = locked_property()
	input_angle = angle_property(default = 0.0)
	output_angle = angle_property(default = 90.0)
	
	def __init__(self,
				 start_point = (0.0, 0.0),
				 radius = 1.0,
				 input_angle=0.0,
				 output_angle = 90.0,
				 angle_step = None,
				 clockwise = False,
				 **kwargs):
		super(shape_bend, self).__init__(
			start_point = start_point,
			radius = radius,
			input_angle = input_angle,
			output_angle = output_angle,
			angle_step = angle_step,
			clockwise = clockwise,
			**kwargs)
		

	def __calc__(self):
		if self.clockwise:
			sign = -1
		else:
			sign = 1
		self.center = (self.start_point[0] - sign * self.radius * math.sin(self.input_angle*DEG2RAD),
			       self.start_point[1] + sign * self.radius * math.cos(self.input_angle*DEG2RAD))
		self.start_angle = self.input_angle - sign * 90.0
		self.end_angle = self.output_angle - sign * 90.0
		shape_arc.__calc__(self)

	def move(self, position):
		self.start_point = coord2(self.start_point[0] + position[0], self.start_point[1] + position[1])
		return self

def shape_bend_rel(start_point = (0.0, 0.0), radius = 1.0, start_angle=0.0, angle_amount = 90.0, angle_step = None):
	""" relative bend: bend with relative turning angle instead of absolute end angle """
	clockwise = bool(angle_amount < 0)
	return shape_bend(start_point, radius, start_angle, start_angle + angle_amount, angle_step, clockwise)

class shape_ellipse(shape_ellipse_arc):
	""" ellipse """
	start_angle = locked_property()
	end_angle = locked_property()
	def __init__ (self,
				  center = (0.0, 0.0),
				  box_size = (1.0, 1.0),
				  angle_step = None, **kwargs):
		super(shape_ellipse, self).__init__(
			center = center,
			box_size = box_size,
			angle_step = angle_step,
			**kwargs)
		self.closed = True
		
	def __calc__ (self):
		self.end_angle = self.start_angle + 360.0
		shape_ellipse_arc.__calc__(self)

	def size_info(self):
		# overlaoded for speed
		return gds_size_info (self.center[0] - 0.5* self.box_size[0], self.center[0] + 0.5* self.box_size[0], 
				      self.center[1] + 0.5* self.box_size[1], self.center[1] - 0.5* self.box_size[1])


class shape_circle(shape_arc, shape_ellipse):
	""" circle """

	def __init__(self,
				 center = (0.0, 0.0),
				 radius = 1.0,
				 angle_step = None,
				 **kwargs):
		super(shape_circle, self).__init__(
			center = center,
			radius = radius,
			angle_step = angle_step,
			**kwargs)

	def __calc__ (self):
		self.end_angle = self.start_angle + 360.0
		shape_arc.__calc__(self)


	def size_info(self):
		# overloaded for speed
		return gds_size_info (self.center[0] - self.radius, self.center[0] + self.radius, 
				      self.center[1] + self.radius , self.center[1] - self.radius)


#----------------------------------------------------------------------------
# (rounded) rectangles and squares
#----------------------------------------------------------------------------

class shape_round_rect(gds_dynamic_shape):
	""" rectangle with rounded corners """
	center = coord2_property(default = (0.0, 0.0))
	box_size = size2_property(default = (1.0, 1.0))
	radius = zero_length_property(default = 1.0)
	angle_step = angle_property(default = 1.0)
	def __init__(self,
				 center = (0.0, 0.0),
				 box_size = (1.0, 1.0),
				 radius = 0,
				 angle_step = None,
				 **kwargs):
		if angle_step == None:
			angle_step = settings.get_angle_step()
		super(shape_round_rect, self).__init__(
			center = center,
			box_size = box_size,
			radius = radius,
			angle_step = angle_step,
			**kwargs)
		self.closed = True

	def __calc__(self):
		cx = self.center[0]
		cy = self.center[1]
		dx = 0.5*self.box_size[0]
		dy = 0.5*self.box_size[1]

		if self.radius <= 0:
			self += [(cx + dx, cy + dy),
						  (cx -dx, cy +dy),
						  (cx -dx, cy -dy),
						  (cx + dx, cy -dy),
						  (cx + dx, cy + dy)]
		else:
			if self.radius > min(self.box_size)/2.0:
				self.radius = min(self.box_size)/2.0

			if (self.radius == self.box_size[0]/2.0) and (self.radius == self.box_size[1]/2.0):
				self += shape_circle(self.center, self.radius, self.angle_step)
			elif self.radius == self.box_size[0]/2.0:
				self += shape_arc((cx,cy+dy - self.radius), self.radius, 0.0, 180.0, self.angle_step)
				self += shape_arc((cx,cy-dy+ self.radius), self.radius, 180.0, 360.0, self.angle_step)
			elif self.radius == self.box_size[1]/2.0:
				self += shape_arc((cx+dx-self.radius,cy), self.radius, 270, 450.0, self.angle_step)
				self += shape_arc((cx-dx+self.radius,cy), self.radius, 90.0, 270.0, self.angle_step)
			else:
				self += shape_arc((cx+dx-self.radius,cy+dy - self.radius), self.radius, 0.0, 90.0, self.angle_step)
				self += shape_arc((cx-dx+self.radius,cy+dy - self.radius), self.radius, 90.0, 180.0, self.angle_step)
				self += shape_arc((cx-dx+self.radius,cy-dy + self.radius), self.radius, 180.0, 270.0, self.angle_step)
				self += shape_arc((cx+dx-self.radius,cy-dy + self.radius), self.radius, 270.0, 360.0, self.angle_step)


	def move(self, position):
		self.center =  coord2(self.center[0] + position[0], self.center[1] + position[1])
		return self

	def size_info(self):
		# overlaoded for speed
		return gds_size_info (self.center[0] - 0.5* self.box_size[0], self.center[0] + 0.5* self.box_size[0] ,
				      self.center[1] + 0.5* self.box_size[1], self.center[1] - 0.5* self.box_size[1])

	def is_empty(self):
		return self.box_size[0] == 0.0 or self.box_size[1] == 0.0


class shape_rect(shape_round_rect):
	""" rectangle """
	radius = locked_property()
	def __init__(self,center = (0.0, 0.0),box_size = (1.0, 1.0), **kwargs):
		super(shape_rect, self).__init__(
			center = center,
			box_size = box_size,
			radius = 0.0,
			**kwargs)
		self.closed = True

	def __calc__(self):
		# overloaded for speed
		cx = self.center[0]
		cy = self.center[1]
		dx = 0.5*self.box_size[0]
		dy = 0.5*self.box_size[1]
		self.points = [(cx + dx, cy + dy),
					  (cx -dx, cy +dy),
					  (cx -dx, cy -dy),
					  (cx + dx, cy -dy)]

class shape_round_rect_arc(gds_dynamic_shape):
	center = coord2_property(default = (0.0, 0.0))
	box_size = size2_property(default = (1.0, 1.0))
	radius = length_property(default = 0.1)
	start_angle = angle_property(default = 0.0)
	end_angle = angle_property(default = 90.0)
	angle_step = angle_property(default = 1.0)
	clockwise = bool_property(default = False)
	def __init__(self,
		     center = (0.0, 0.0),
		     box_size = (1.0, 1.0),
		     radius = 0.1,
		     start_angle=0.0,
		     end_angle = 90.0,
		     angle_step = None,
		     clockwise = False,
		     **kwargs):
		if angle_step == None:
			angle_step = settings.get_angle_step()
		super(shape_round_rect_arc, self).__init__(
			center = center,
			box_size = box_size,
			radius = radius,
			start_angle = start_angle,
			end_angle = end_angle,
			angle_step = angle_step,
			clockwise = clockwise,
			**kwargs)
	

	def __calc__(self):
		cx = self.center[0]
		cy = self.center[1]
		dx = 0.5*self.box_size[0]
		dy = 0.5*self.box_size[1]
		self.clear()
		if self.clockwise:
			as_sign = -1
		else:
			as_sign = 1
		# restrict radius
		if self.radius > min(self.box_size)/2.0:
			self.radius = min(self.box_size)/2.0
		# radius = box: circle arc
		if (self.radius == self.box_size[0]/2.0) and (self.radius == self.box_size[1]/2.0):
			self += shape_arc(self.center, self.radius, self.start_angle, self.end_angle, self.angle_step, self.clockwise)
		# radius = zero: part of rectangle
		elif self.radius <= 0:
			for a in arange(self.start_angle, self.end_angle + 45.0, as_sign * 90.0):
				self += [(cx + sign(math.cos(DEG2RAD* a)) * dx, cy + sign(math.sin(DEG2RAD* a)) * dy)]
		# arbitrary
		else:
			for a in arange(self.start_angle, self.end_angle + 45.0, as_sign * 90.0):
				start = max(self.start_angle, a-a%90.0 + 45.0 - as_sign*45.0)
				end = min(self.end_angle, a-a%90.0 + 45.0 + as_sign * 45.0)
				self += shape_arc((cx + sign(math.cos(DEG2RAD* a)) * (dx-self.radius), cy + sign(math.sin(DEG2RAD* a)) * (dy-self.radius)), self.radius, start, end, self.angle_step, self.clockwise)
				

		gds_shape.remove_identicals(self)
				
class shape_regular_polygon(gds_dynamic_shape):
	""" regular N-sided polygon """
	center = coord2_property(default = (0.0, 0.0))
	radius = length_property(default = 1.0)
	n_o_sides = int_property(default = 8, restriction = restrict_range(lower = 3))
	def __init__(self, center = (0.0, 0.0),radius = 1.0, n_o_sides=8, **kwargs):
		super(shape_regular_polygon, self).__init__(
			center = center,
			radius = radius,
			n_o_sides = n_o_sides,
			**kwargs)
		self.closed = True

	def __calc__(self):
		if self.radius == 0.0: 
			self.append(self.center)
			return 
		angle_step = 2 * math.pi / self.n_o_sides
		for i in xrange (0, self.n_o_sides + 1):
			self.append ((self.center[0] + self.radius * math.cos((i+0.5) * angle_step + math.pi/2),
							  self.center[1] + self.radius * math.sin((i+0.5) * angle_step + math.pi/2)))

	def move(self, position):
		self.center =  coord2(self.center[0] + position[0], self.center[1] + position[1])
		return self

	def is_empty(self):
		return self.radius == 0.0


class shape_wedge(gds_dynamic_shape):
	""" wedge, or symmetric trapezium. specified by the center of baselines and the length of the baselines """
	begin_coord = coord2_property(default = (0.0, 0.0))
	end_coord = coord2_property(default = (0.0, 0.0))
	begin_width = zero_length_property(default = 3.0)
	end_width = zero_length_property(default = 1.0)
	def __init__ (self, begin_coord=(0.0,0.0), end_coord = (10.0, 0.0), begin_width = 3.0, end_width = 1.0, **kwargs):
		super(shape_wedge, self).__init__(
			begin_coord = begin_coord,
			end_coord = end_coord,
			begin_width = begin_width,
			end_width = end_width,
			**kwargs)
		self.closed = True

	def __calc__(self):
		dist = distance(self.end_coord, self.begin_coord)
		cosangle = (self.end_coord[0] - self.begin_coord[0])/dist
		sinangle = (self.end_coord[1] - self.begin_coord[1])/dist
		self += [ (self.begin_coord[0] + sinangle * self.begin_width/2.0 , self.begin_coord[1] - cosangle * self.begin_width/2.0),
			  (self.begin_coord[0] - sinangle * self.begin_width/2.0 , self.begin_coord[1] + cosangle * self.begin_width/2.0),
			  (self.end_coord[0]   - sinangle * self.end_width/2.0   , self.end_coord[1]   + cosangle * self.end_width/2.0),
			  (self.end_coord[0]   + sinangle * self.end_width/2.0   , self.end_coord[1]   - cosangle * self.end_width/2.0)]

	def move(self, position):
		self.begin_coord = (self.begin_coord[0] + position[0], self.begin_coord[1] + position[1])
		self.end_coord = (self.end_coord[0] + position[0], self.end_coord[1] + position[1])
		return self

	def is_empty(self):
		return self.begin_coord == self.end_coord



class shape_radial_wedge(gds_dynamic_shape):
	""" radial wedge: the coordinates of the start and end point are specified in polar coordinates
	    from a given center """
	center = coord2_property(default = (0.0, 0.0))
	inner_radius = length_property(required = True)
	outer_radius = length_property(required = True)
	inner_width = length_property(required = True)
	outer_width = length_property(required = True)
	angle = normalized_angle_property(required = True)
	def __init__(self, center, inner_radius, outer_radius, inner_width, outer_width, angle, **kwargs):
		super(shape_radial_wedge , self).__init__(
			center = center,
			inner_radius = inner_radius,
			outer_radius = outer_radius,
			inner_width = inner_width,
			outer_width = outer_width,
			angle = angle,
			**kwargs)
		self.closed = True

	def __calc__(self):
		cosangle = math.cos(self.angle * DEG2RAD)
		sinangle = math.sin(self.angle * DEG2RAD)
		bc = (self.center[0] + self.inner_radius * math.cos(self.angle*DEG2RAD), self.center[1] + self.inner_radius * math.sin(self.angle*DEG2RAD))
		ec = (self.center[0] + self.outer_radius * math.cos(self.angle*DEG2RAD), self.center[1] + self.outer_radius * math.sin(self.angle*DEG2RAD))
		self += [ (bc[0] + sinangle * self.inner_width/2.0, bc[1] - cosangle * self.inner_width/2.0),
			  (bc[0] - sinangle * self.inner_width/2.0, bc[1] + cosangle * self.inner_width/2.0),
			  (ec[0] - sinangle * self.outer_width/2.0, ec[1] + cosangle * self.outer_width/2.0),
			  (ec[0] + sinangle * self.outer_width/2.0, ec[1] - cosangle * self.outer_width/2.0)]

	def move(self, position):
		self.center =  (self.center[0] + position[0], self.center[1] + position[1])
		return self

	def is_empty(self):
		return self.inner_radius == self.outer_radius


class shape_parabolic(gds_dynamic_shape):
	""" parabolic wedge (taper) """
	begin_coord = coord2_property(default = (0.0, 0.0))
	end_coord = coord2_property(default = (0.0, 0.0))
	begin_width = zero_length_property(default = 3.0)
	end_width = zero_length_property(default = 1.0)
	def __init__(self, begin_coord=(0.0,0.0), end_coord = (10.0, 0.0), begin_width = 3.0, end_width = 1.0, **kwargs):
		super(shape_parabolic, self).__init__(
		begin_coord = begin_coord,
		end_coord = end_coord,
		begin_width = begin_width,
		end_width = end_width,
		**kwargs)
		self.closed = True

	def __calc__(self):
		if (self.begin_width > self.end_width):
			ew = self.begin_width
			ec = self.begin_coord
			bw = self.end_width
			bc = self.end_coord
		else:
			bw = self.begin_width
			bc = self.begin_coord
			ew = self.end_width
			ec = self.end_coord

		length = distance(ec, bc)
		angle = angle_rad(ec, bc)
		sinangle = math.sin(angle)
		cosangle = math.cos(angle)

		#dx=2 * get_grid()/get_unit()
		dx = 0.01

		if abs(ew - bw) < dx:
			self.extend ([ (bc[0] + sinangle * bw/2.0, bc[1] - cosangle * bw/2.0),
						(bc[0] - sinangle * bw/2.0, bc[1] + cosangle * bw/2.0),
						(ec[0] - sinangle * bw/2.0, ec[1] + cosangle * ew/2.0),
						(ec[0] + sinangle * bw/2.0, ec[1] - cosangle * ew/2.0),
						(bc[0] + sinangle * bw/2.0, bc[1] - cosangle * bw/2.0)])
			return

		if length < 0.0025:
			return

		a = 4.0 * length /(ew**2-bw**2)
		y0 = a * bw**2 / 4.0
		y = y0
		width = bw

		right_shape =[(bc[0] + sinangle * bw/2.0, bc[1] - cosangle * bw/2.0)]
		left_shape = [(bc[0] - sinangle * bw/2.0, bc[1] + cosangle * bw/2.0)]

		READY = False
		while( not READY):
			width = width + 4 * dx + 4 * math.sqrt(dx* ( width + dx))
			y = a * width**2 /4.0

			if ( y - y0 > length):
				READY = True
				coord = ec
				width = ew
			else:
				coord = (bc[0] + (y-y0) * cosangle, bc[1] + (y-y0) * sinangle)

			right_shape.append((coord[0] + sinangle * width/2.0, coord[1] - cosangle * width/2.0))
			left_shape.append((coord[0] - sinangle * width/2.0, coord[1] + cosangle * width/2.0))

		right_shape.reverse()
		self += left_shape
		self += right_shape

	def move(self, position):
		self.begin_coord = (self.begin_coord[0] + position[0], self.begin_coord[1] + position[1])
		self.end_coord = (self.end_coord[0] + position[0], self.end_coord[1] + position[1])
		return self

	def is_empty(self):
		return self.begin_coord == self.end_coord


class shape_ring_segment(gds_dynamic_shape):
	""" ring segment """
	center = coord2_property(default = (0.0, 0.0))
	angle_start = angle_property(default = 0.0)
	angle_end = angle_property(default = 90.0)
	inner_radius = length_property(required = True)
	outer_radius = length_property(required = True)
	angle_step = angle_property(required = True)
	
	def __init__ (self, center, angle_start, angle_end, inner_radius, outer_radius, angle_step = None, **kwargs):
		if angle_step == None:
			angle_step = settings.get_angle_step()
		super(shape_ring_segment, self).__init__(
			center = center,
			angle_start = angle_start,
			angle_end = angle_end,
			inner_radius = inner_radius,
			outer_radius = outer_radius,
			angle_step = angle_step,
			**kwargs)
		self.closed = True

	def __calc__(self):
		self += shape_arc(self.center, self.inner_radius, self.angle_start, self.angle_end, self.angle_step)
		gds_shape.reverse(self) # do not destroy dynamism
		self += shape_arc(self.center, self.outer_radius, self.angle_start, self.angle_end, self.angle_step)

	def move(self, position):
		self.center =  (self.center[0] + position[0], self.center[1] + position[1])
		return self

	def is_empty(self):
		return self.inner_radius == self.outer_radius or self.angle_start == self.angle_end


class shape_hexagon(shape_regular_polygon):
	""" hexagon """
	def __init__(self, center = (0.0, 0.0),radius = 1.0, **kwargs):
		super(shape_hexagon, self).__init__(
			center = center, 
			radius = radius,
			n_o_sides = 6,
			**kwargs)

class shape_dodecagon(shape_regular_polygon):
	""" dodecagon """
	def __init__(self, center = (0.0, 0.0),radius = 1.0, **kwargs):
		super(shape_dodecagon, self).__init__(
			center = center,
			radius = radius ,
			n_o_sides = 12,
			**kwargs)

class shape_cross(gds_dynamic_shape):
	""" cross. thickness sets the width of the arms """
	center = coord2_property(default = (0.0, 0.0))
	box_size = length_property(default = 20.0)
	thickness = length_property(default = 5.0)
	def __init__(self, center = (0.0, 0.0),box_size=20.0, thickness = 5.0, **kwargs):
		super(shape_cross, self).__init__(
			center = center,
			box_size = box_size,
			thickness = thickness,
			**kwargs)
		
		self.closed = True

	def __calc__(self):
		self += [(self.center[0]-self.box_size/2.0, self.center[1]-self.thickness/2.0),
		   (self.center[0]-self.box_size/2.0, self.center[1]+self.thickness/2.0),
		   (self.center[0]-self.thickness/2.0, self.center[1]+self.thickness/2.0),
		   (self.center[0]-self.thickness/2.0, self.center[1]+self.box_size/2.0),
		   (self.center[0]+self.thickness/2.0, self.center[1]+self.box_size/2.0),
		   (self.center[0]+self.thickness/2.0,self.center[1]+self.thickness/2.0),
		   (self.center[0]+self.box_size/2.0,self.center[1]+self.thickness/2.0),
		   (self.center[0]+self.box_size/2.0,self.center[1]-self.thickness/2.0),
		   (self.center[0]+self.thickness/2.0,self.center[1]-self.thickness/2.0),
		   (self.center[0]+self.thickness/2.0,self.center[1]-self.box_size/2.0),
		   (self.center[0]-self.thickness/2.0,self.center[1]-self.box_size/2.0),
		   (self.center[0]-self.thickness/2.0,self.center[1]-self.thickness/2.0),
		   (self.center[0]-self.box_size/2.0, self.center[1]-self.thickness/2.0)]
		 

	def move(self, position):
		self.center =  coord2(self.center[0] + position[0], self.center[1] + position[1])
		return self

	def size_info(self):
		# overlaoded for speed
		return gds_size_info (self.center[0] - 0.5* self.box_size[0], self.center[0] - 0.5* self.box_size[0] ,
				       self.center[1] + 0.5* self.box_size[1], self.center[1] - 0.5* self.box_size[1])

	def is_empty(self):
		return self.box_size == 0.0 or self.thickness == 0.0
