Yes I the code above gets the minimum enclosing rectangle (well, really just the properly rotated and sized Bounding Box–or more precisely: the TextBox) that surrounds the text. The Bounding Box does take rotation into account, but reports the minimum enclosing orthogonal rectangle.
I’ve finally gotten the correct orientation on text strokes for text within modules.
The code above seems to get the correct Text Box orientation. But it is necessary to use TransormTextShapeToSegmentList() to get the individual DRAWSEGMENT objects (line segments) that make up the text strokes.
I’ve finally decoded how to get the properly rotated segment list. The difficulty is that it is different whether you are getting the text from TEXTE_PCB and TEXTE_MODULE. This seems an odd design choice, but this is what I have figured out:
# Excerpt of python code for pcbnew that creates line
# segments ('DRAWSEGMENT') from the individual strokes of text.
#
# 'object' here is a text object of type TEXTE_MODULE or TEXTE_PCB
#
# The following 'try' differentiates TEXTE_PCB from TEXTE_MODULE
# There is probably a more efficient way to determine the type :-)
# perhaps using if type(object) == pcbnew.TEXTE_MODULE:
# TEXTE_MODULE: oddly, the combination of draw rotation and
# orientation is what's needed to determine the correct
# segments transformation only for TEXTE_MODULE object.
try:
orientation = object.GetDrawRotation() - object.GetOrientation() # ccw from x-axis
except:
# TEXTE_PCB:
# Already returns segments that are rotated for display.
orientation = 0
self.DrawVector(self.GetRotatedVector(vector,center,orientation),
layer=pcbnew.Eco1_User, #USER_draw_outlines_layer,
thickness=USER_draw_stroke_thickness)
def DrawVector(self,vector,layer=pcbnew.Eco2_User,thickness=0.015):
'''wxPoint_vector'''
#print type(vector)
for i in range(0,len(vector)-1,2):
self.DrawSeg(
vector[i][0],
vector[i][1],
vector[i+1][0],
vector[i+1][1],
layer=layer,
thickness=thickness)
def DrawSeg(self,x1,y1,x2,y2,layer=pcbnew.Dwgs_User,thickness=0.15):
b=self._board or pcbnew.GetBoard()
ds=pcbnew.DRAWSEGMENT(b)
b.Add(ds)
ds.SetStart(pcbnew.wxPoint(x1,y1))
ds.SetEnd(pcbnew.wxPoint(x2,y2))
ds.SetLayer(layer)#B.SilkS"])
ds.SetWidth(int(thickness*pcbnew.IU_PER_MM))
def GetRotatedVector(self,vector,center,orientation):
# return immediately if there's nothing to rotate
if len(vector) == 0:
return vector
# the center is the rotation point
# common equations for all points in this vector
ox,oy = center
orientation = -orientation/10.0
cos= math.cos(math.radians(orientation))
sin= math.sin(math.radians(orientation))
rpoints = pcbnew.wxPoint_Vector(0)
for v in vector:
px=v[0]; py=v[1]
# rotate point around center
pox = px-ox
poy = py-oy
nx = cos * (pox) - sin * (poy) + ox
ny = sin * (pox) + cos * (poy) + oy
rpoints.append(pcbnew.wxPoint(int(nx),int(ny)))
# add the start point to form a closed polygon
rpoints.append(rpoints[0])
return rpoints