虽然地球是球面,但由于地球很大,小范围的地理位置可以用平面直角坐标表示,例如我们通常使用的城市交通地图。这样我们需要解决纵横坐标的及其方向、原点位置和坐标单位长度问题。
通常,我们选取从西到东为x轴的正向、从南到北为y轴的正向;原点位置和坐标单位长度需要根据具体问题来确定。原点一般定在最主要的参考点(其他位置是这个参考点的相对值);如果没有参考点,原点定在我们考虑的对象范围的左下角,也就是说要标定的东西都在坐标系的第一象限的中心位置。坐标单位长度要使所有标定对象的占据的矩形范围不小于三分之二和不大于十分之九的坐标系矩形画布范围。这些通常的规则只是为了迎合人们的习惯,不过一定不可以把对象标定在坐标系矩形画布外。
例题:根据以下条件画一幅示意图,标出学校和小刚家、小强家、小敏家的位置。
小刚家:出校门向东走1500m,再向北走2000m。
小强家:出校门向西走2000m,再向北走3500m,最后向东走500m。
小敏家:出校门向南走1000m,再向东走3000m,最后向南走750m。
分析:很明显,学校是主要参考点,定为坐标原点;东西范围2000m+3000m=5000m,南北范围3500m+1000m=4500m,实际画布大小就定为5500m×5000m(坐标单位1m)。这么大的画布不可能画在纸上,因此纸上的坐标单位定为100m,用1cm作为1个坐标单位作图,也就是说比例尺是1:10000。手工作图费时费力,这里用Python海龟画图进行绘画:用10像素表示1个坐标单位,那画布大小是550×500像素。
Python源程序代码(图片):
Python源程序代码(源码):
见附录1。
绘制出的精美图片:
用函数轨迹模块(附录2)和海龟画图完成下面练习题:
1、如图,这是一所学校的平面示意图,建立适当的平面直角坐标系,并用坐标表示教学楼、图书馆、校门、实验楼、国旗杆的位置。
2、如图,这是一个利用平面直角坐标系画出的某动物园的示意图,如果这个坐标系分别以正东、正北方向为x轴、y轴的正方向,并且猴山和狮虎山的坐标分别是(2,1)和(8,2)。你能在此图上标出熊猫馆(6,6)的位置吗?
3、近年来,园林部门为了对古树名木进行系统养护,建立了相关的地理信息系统,其中重要的一条就是要确定这些树的位置。如下图,某小区有树龄百年以上的古松树4棵(S1,S2,S3,S4),古槐树6棵(H1,H2,H3,H4,H5,H6)。为了加强对古树的保护,园林部门将4棵古松树的位置用坐标表示为S1(3,9),S2(5,10),S3(11,6),S4(12,11)类似地,你能在下图中把6棵古槐树的位置也用坐标表示出来吗?
附录1:
#用坐标表示小范围地理位置
#预制自定义模块(py文件)存放根目录
import sys
sys.path.append("/data/5xstar/pyfiles")
#导入海龟画图并初始化窗口和画布
import turtle as t
t.setup(650,600) #窗口大小
t.screensize(550,500) #画布大小
t.shape("circle") #海龟形状圆点
t.shapesize(0.25,0.25) #四分之一大小
#导入函数轨迹模块
from mymath.rcs import *
#x轴数值与像素对应元组100:10
xUnt = (1,10) #1表示100,防止数字打不下
#y轴数值与像素对应元组100:10
yUnt = (1,10) #1表示100
#自定义坐标元组(左下角x坐标, 左下角y坐标, 右上角x坐标, 右上角y坐标)
wc = (-225,-125,325,375)
#画平面直角坐标系
build(t,xUnt,yUnt,wc)
#提笔
t.up()
#标位置字体
workFont=("宋体", 12, "bold")
#标定位置
def indication(name,pos,dx=2,dy=2,algn=None):
'''
@name 位置名称
@pos 位置坐标
@dx 写字位置x增加值
@dy 写字位置y增加值
@align 写字方向:center,left,right
'''
t.setpos(pos)
t.stamp()
t.setpos(pos[0]+dx,pos[1]+dy)
if algn == None:
t.write("%s(%d,%d)" % (name, pos[0]*10, pos[1]*10), font=workFont) #实际坐标是像素数的十倍
else:
t.write("%s(%d,%d)" % (name, pos[0]*10, pos[1]*10), align=algn, font=workFont)
#标定学校位置(原点)
indication("学校",(0,0),5,5)
#标定小刚家的位置(1500,2000)
indication("小刚家",(150,200))
#标定小强家的位置(-2000,3500)
indication("小强家",(-200,350))
#标定小敏家的位置(3000,-1000)
indication("小敏家",(300,-100),dx=-2,algn="right")
#隐藏画笔
t.ht()
附录2:
'''初中平面直角坐标系中单调函数轨迹、画直线和打点
@作者 码老师
@微信公众号 学思营 ID:xuesying
@公司 深圳五行星软件有限公司
@日期 2020-12-19
@使用方法
1、导入海龟画图并初始化窗口和画布,例如:
import turtle as t
t.setup(600,600)
t.screensize(400,400)
t.shape("turtle")
2、导入本模块:
from rcs import *
3、用下面函数:
build(aTurtle, xUnt = None, yUnt = None, wc = None):
@aTurtle 一个海龟
@xUnt x轴数值与像素对应元组
@yUnt y轴数值与像素对应元组
@wc 自定义坐标元组(llx, lly, urx, ury)
@llx -- 一个数值, 画布左下角的 x-坐标(像素)
@lly -- 一个数值, 画布左下角的 y-坐标
@urx -- 一个数值, 画面右上角的 x-坐标
@ury -- 一个数值, 画布右上角的 y-坐标
画平面直角坐标系,例如:
build(t) #, worldcoordinates=(0,0,400,400))
4、使用模块进行画单调函数轨迹、直线和打点
(1)画函数轨迹
第一步:定义一个单调函数例如:
def fun(x):
return 5*x + 3
第二步:获取x,y的取值范围:
minx, maxx, miny, maxy = getRange()
第三步(可选):根据x,y的取值范围和函数的实际要求,确定自变量取值范围:
x1,x2
第四步:调用下面函数:
trace(aTurtle, x1, x2, fun):
@aTurtle 一个海龟
@x1 自变量一端点值
@x2 自变量另一端点值
@fun 单调函数
画函数轨迹,例如:
#一元一次函数
def fun(x):
return 2*x + 1
trace(t, 50, -50, fun)
(2)画直线段
第一步:获取x,y的取值范围:
minx, maxx, miny, maxy = getRange()
第二步:调用下面函数:
line(aTurtle, x1, y1, x2, y2):
@aTurtle 一个海龟
@x1,y1 始点
@x2,y2 终点
画直线段,例如画对角线:
line(t, minx, miny, maxx, maxy)
(3)打圆点
第一步:获取x,y的取值范围:
minx, maxx, miny, maxy = getRange()
第二步:调用下面函数:
circularDot(aTurtle, x, y, size=None, *color):
@aTurtle 一个海龟
@x,y 坐标
@size 圆点大小
@color 圆点颜色
打圆点,例如下降对角线打点:
x, y = minx, maxy
size = 1
while True:
if x > maxx or y < miny:
break
circularDot(t, x, y, size, "red")
x += 1
y -= 1
size += 1
'''
#导入分数
from fractions import Fraction
#坐标轴线宽
axisWidth = 1
#坐标轴和坐标点颜色
axisColor = "black"
#坐标箭头
axisTurtle = "classic"
#箭头大小 原来四分之一 轮廓线1
axisShapesize = (0.8, 0.8, 1)
#数轴单位(整数)及其对应的像素大小(整数) 1对应10像素
xUnit = [1, 20]
yUnit = [1, 20]
#方格线宽
squareWidth = 1
#方格线色 浅蓝
squareColor = "#EFEFFF"
#数点线长
markLen = 5
#数字字体
markFont=("Arial", 8, "normal")
#坐标系,调用build后才有值
worldcoordinates = None
#检测数轴单位
def __checkUnit(unt):
if unt != None and len(unt) == 2:
return isinstance(unt[0],int) and isinstance(unt[0],int)
return False
#建立直角坐标系
def build(aTurtle, xUnt = None, yUnt = None, wc = None):
'''按初中课本使用的直角坐标系绘图
@aTurtle 一个海龟
@xUnt x轴数值与像素对应元组
@yUnt y轴数值与像素对应元组
@wc 自定义坐标元组(llx, lly, urx, ury)
@llx -- 一个数值, 画布左下角的 x-坐标(像素)
@lly -- 一个数值, 画布左下角的 y-坐标
@urx -- 一个数值, 画面右上角的 x-坐标
@ury -- 一个数值, 画布右上角的 y-坐标'''
#保持海龟原来的参数后设置参数
speed = aTurtle.speed()
aTurtle.speed(0)
width = aTurtle.pensize()
pencolor = aTurtle.pencolor()
shape = aTurtle.shape()
shapesize = aTurtle.shapesize()
isdown = aTurtle.isdown()
pos = aTurtle.pos()
heading =aTurtle.heading()
#数量与像素的对应关系
if __checkUnit(xUnt):
xUnit[0] = xUnt[0]
xUnit[1] = xUnt[1]
if __checkUnit(yUnt):
yUnit[0] = yUnt[0]
yUnit[1] = yUnt[1]
global worldcoordinates
#自定义坐标
if wc != None and len(wc) == 4:
worldcoordinates = wc
aTurtle.setworldcoordinates(*worldcoordinates) #自定义坐标系
else:
temp = aTurtle.screensize()
worldcoordinates = (-temp[0]/2,-temp[1]/2,temp[0]/2,temp[1]/2)
#定坐标方向
xh = worldcoordinates[0] < worldcoordinates[2]
if xh: #True从左到右
x1,x2 = int(worldcoordinates[0]), int(worldcoordinates[2])
else:
x1,x2 = int(worldcoordinates[2]), int(worldcoordinates[0])
yh = worldcoordinates[1] < worldcoordinates[3]
if yh: #True从下到上
y1,y2 = int(worldcoordinates[1]), int(worldcoordinates[3])
else:
y1,y2 = int(worldcoordinates[3]), int(worldcoordinates[1])
#画方格线
#画与y轴平行的线
if isdown:
aTurtle.up()
for i in range(-xUnit[1], x1, -xUnit[1]):
aTurtle.pencolor(squareColor)
aTurtle.pensize(squareWidth)
aTurtle.setpos(i,y1)
aTurtle.down()
aTurtle.sety(y2)
aTurtle.up()
aTurtle.sety(0)
aTurtle.down()
aTurtle.pencolor(axisColor)
aTurtle.pensize(axisWidth)
aTurtle.sety(markLen)
aTurtle.up()
if yh: #标x数字
aTurtle.sety(-markLen-markFont[1]) #还要下降字体高度
else:
aTurtle.sety(-markLen//2) #无需下降字体高度
aTurtle.write(i//xUnit[1]*xUnit[0], align="center", font = markFont)
for i in range(xUnit[1], x2, xUnit[1]):
aTurtle.pencolor(squareColor)
aTurtle.pensize(squareWidth)
aTurtle.setpos(i,y1)
aTurtle.down()
aTurtle.sety(y2)
aTurtle.up()
aTurtle.sety(0)
aTurtle.down()
aTurtle.pencolor(axisColor)
aTurtle.pensize(axisWidth)
aTurtle.sety(markLen)
aTurtle.up()
if yh:
aTurtle.sety(-markLen-markFont[1])
else:
aTurtle.sety(-markLen//2)
aTurtle.write(i//xUnit[1]*xUnit[0], align="center", font = markFont)
#画与x轴平行的线
for i in range(-yUnit[1], y1, -yUnit[1]):
aTurtle.pencolor(squareColor)
aTurtle.pensize(squareWidth)
aTurtle.setpos(x1, i)
aTurtle.down()
aTurtle.setx(x2)
aTurtle.up()
aTurtle.setx(0)
aTurtle.down()
aTurtle.pencolor(axisColor)
aTurtle.pensize(axisWidth)
aTurtle.setx(markLen)
aTurtle.up()
if yh: #标y数字
aTurtle.setpos(-markLen//2, i-markFont[1]//2) #下降字体高度一半
else:
aTurtle.setpos(-markLen//2, i+markFont[1]//2)
if xh:
aTurtle.write(i//yUnit[1]*yUnit[0], align="right", font = markFont)
else:
aTurtle.write(i//yUnit[1]*yUnit[0], font = markFont)
for i in range(yUnit[1], y2, yUnit[1]):
aTurtle.pencolor(squareColor)
aTurtle.pensize(squareWidth)
aTurtle.setpos(x1, i)
aTurtle.down()
aTurtle.setx(x2)
aTurtle.up()
aTurtle.setx(0)
aTurtle.down()
aTurtle.pencolor(axisColor)
aTurtle.pensize(axisWidth)
aTurtle.setx(markLen)
aTurtle.up()
if yh:
aTurtle.setpos(-markLen//2, i-markFont[1]//2)
else:
aTurtle.setpos(-markLen//2, i+markFont[1]//2)
if xh:
aTurtle.write(i//yUnit[1]*yUnit[0], align="right", font = markFont)
else:
aTurtle.write(i//yUnit[1]*yUnit[0], font = markFont)
#画坐标
aTurtle.pencolor(axisColor)
aTurtle.pensize(axisWidth)
aTurtle.shape(axisTurtle)
aTurtle.shapesize(*axisShapesize)
aTurtle.up()
aTurtle.setpos(x1, 0)
aTurtle.down()
aTurtle.setx(x2)
if xh:
aTurtle.seth(0)
else:
aTurtle.seth(180)
aTurtle.stamp()
aTurtle.up()
if yh:
aTurtle.sety(-markLen-markFont[1])
else:
aTurtle.sety(-markLen//2)
aTurtle.write('x', align="center", font = markFont)
aTurtle.setpos(0, y1)
aTurtle.down()
aTurtle.sety(y2)
if yh:
if xh:
aTurtle.seth(90)
else:
aTurtle.seth(-90)
else:
if xh:
aTurtle.seth(90)
else:
aTurtle.seth(-90)
aTurtle.stamp()
aTurtle.up()
if yh:
aTurtle.setpos(-markLen//2, y2-markFont[1])
else:
aTurtle.setx(-markLen//2)
if xh:
aTurtle.write('y', align="right", font = markFont)
else:
aTurtle.write('y', font = markFont)
#标注原点
if yh:
aTurtle.setpos(-markLen//2, -markLen-markFont[1])
else:
aTurtle.setpos(-markLen//2, -markLen//2)
if xh:
aTurtle.write(0, align="right", font = markFont)
else:
aTurtle.write(0, font = markFont)
#恢复海龟原来的设置参数
aTurtle.speed(speed)
aTurtle.shape(shape)
aTurtle.pensize(width)
aTurtle.pencolor(pencolor)
aTurtle.shapesize(*shapesize)
aTurtle.setpos(*pos)
aTurtle.seth(heading)
if isdown:
aTurtle.down()
#检查是否已经初始化
def __checkBuild():
if worldcoordinates == None:
print("还没有画坐标,请调用build(aTurtle, xUnt = None, yUnt = None, worldcoordinates = None)函数画坐标")
return False
else:
return True
#屏幕上进1像素实际的值之间的转换
def __pixchange():
#屏幕上进1像素实际的值之间的转换
dx, udx, dy, udy = Fraction(*xUnit), Fraction(xUnit[1], xUnit[0]), Fraction(*yUnit), Fraction(yUnit[1], yUnit[0])
#x坐标作图范围
if worldcoordinates[0] < worldcoordinates[2]:
minx, maxx = dx * worldcoordinates[0], dx * worldcoordinates[2]
else:
minx, maxx = dx * worldcoordinates[2], dx * worldcoordinates[0]
#y坐标作图范围
if worldcoordinates[1] < worldcoordinates[3]:
miny, maxy = dy * worldcoordinates[1], dy * worldcoordinates[3]
else:
miny, maxy = dy * worldcoordinates[3], dy * worldcoordinates[1]
return dx, udx, dy, udy, minx, maxx, miny, maxy
#函数轨迹
def trace(aTurtle, x1, x2, fun):
'''函数轨迹
@aTurtle 一个海龟
@x1 自变量一端点值
@x2 自变量另一端点值
@fun 单调函数'''
#自变量检查
if x1 == x2:
print("自变量不可以相等")
return False
#检查是否已经画坐标
if not __checkBuild():
return False
#保持海龟落笔状态
isdown = aTurtle.isdown()
speed = aTurtle.speed()
aTurtle.speed(0)
pos = aTurtle.pos()
if isdown:
aTurtle.up()
if x1 > x2: #交换自变量
temp = x1
x1 = x2
x2 = temp
#屏幕上进1像素实际的值之间的转换
dx, udx, dy, udy, minx, maxx, miny, maxy = __pixchange()
if x2 <= minx or x1 >= maxx:
print("自变量不在%s到%s范围内!" % (str(minx), str(maxx)))
return False
if x1 < minx:
x1 = minx
if x2 > maxx:
x2 = maxx
#起点
x = x1
y = fun(x1)
if y >= miny and y<= maxy:
aTurtle.setpos(udx*x, udy*y)
aTurtle.down()
#描图
while True:
x += dx
if x > x2: #过了终点
break
y = fun(x)
if y >= miny and y<= maxy:
aTurtle.setpos(udx*x, udy*y)
if not aTurtle.isdown():
aTurtle.down()
else:
if aTurtle.isdown():
aTurtle.setpos(udx*x, udy*y)
aTurtle.up()
if aTurtle.isdown():
aTurtle.up()
aTurtle.setpos(*pos)
aTurtle.speed(speed)
#恢复下笔状态
if isdown:
aTurtle.down()
return True
#作图范围
def getRange():
'''作图范围
@return x坐标最小值,x坐标最大值,y坐标最小值,y坐标最大值'''
#检查是否已经画坐标
if not __checkBuild():
return None
#屏幕上进1像素实际的值之间的转换
dx, udx, dy, udy, minx, maxx, miny, maxy = __pixchange()
return minx, maxx, miny, maxy
#作图范围字符串
def __rangestr(minx, maxx, miny, maxy):
return "%s≤x≤%s,%s≤y≤%s" % (str(minx),str(maxx),str(miny),str(maxy))
#画线段
def line(aTurtle, x1, y1, x2, y2):
'''画线段
@aTurtle 一个海龟
@x1,y1 始点
@x2,y2 终点'''
#检查是否已经画坐标
if not __checkBuild():
return False
#屏幕上进1像素实际的值之间的转换
dx, udx, dy, udy, minx, maxx, miny, maxy = __pixchange()
if min(x1, x2) < minx or max(x1, x2) > maxx or min(y1, y2) < miny or max(y1, y2) > maxy:
print("有端点不在作图范围(%s)内!" % __rangestr(minx, maxx, miny, maxy))
return False
#保持海龟落笔状态
isdown = aTurtle.isdown()
pos = aTurtle.pos()
speed = aTurtle.speed()
aTurtle.speed(0)
if isdown:
aTurtle.up()
aTurtle.setpos(udx*x1, udy*y1)
aTurtle.down()
aTurtle.setpos(udx*x2, udy*y2)
aTurtle.up()
aTurtle.setpos(*pos)
aTurtle.speed(speed)
if isdown:
aTurtle.down()
return True
#打圆点
def circularDot(aTurtle, x, y, size=None, *color):
'''打点
@aTurtle 一个海龟
@x,y 坐标
@size 圆点大小
@color 圆点颜色'''
#检查是否已经画坐标
if not __checkBuild():
return False
#屏幕上进1像素实际的值之间的转换
dx, udx, dy, udy, minx, maxx, miny, maxy = __pixchange()
if x< minx or x > maxx or y < miny or y > maxy:
print("该点点不在作图范围(%s)内!" % __rangestr(minx, maxx, miny, maxy))
return False
isdown = aTurtle.isdown()
pos = aTurtle.pos()
speed = aTurtle.speed()
aTurtle.speed(0)
if isdown:
aTurtle.up()
aTurtle.setpos(udx*x, udy*y)
if color == None:
aTurtle.dot(size)
else:
aTurtle.dot(size, *color)
aTurtle.setpos(*pos)
aTurtle.speed(speed)
if isdown:
aTurtle.down()
return True
if __name__ == "__main__":
import turtle as t
t.setup(600,600)
t.screensize(400,400)
t.shape("turtle")
build(t) #, worldcoordinates=(0,0,400,400))
#一元一次函数
def fun1(x):
return 2*x + 1
trace(t, 50, -50, fun1)
#一元二次函数
def fun2(x):
return x**2 + 2*x + 2
trace(t, 50, -50, fun2)
#画圆
def fun3(x):
return (5**2 - x**2)**0.5
trace(t, 5, -5, fun3)
def fun4(x):
return -(5**2 - x**2)**0.5
trace(t, 5, -5, fun4)
#画对角线
minx, maxx, miny, maxy = getRange()
line(t, minx, miny, maxx, maxy)
#打点对角线
x, y = minx, maxy
size = 1
while True:
if x > maxx or y < miny:
break
circularDot(t, x, y, size, "red")
x += 1
y -= 1
size += 1
t.mainloop()