Python Forum
[PyQt] Draw an Arc, not a Wedge
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyQt] Draw an Arc, not a Wedge
#1
Hi,
I'd like to NOT draw the arms of the wedge and just show an arc please!? (Using QGraphicsScene, QGraphicsView)

I'm using an ellipse, I believe that is right?

def item_add_arc(self, data):
	
	#https://doc.qt.io/archives/qt-5.15/qgraphicsellipseitem.html
	
	o = QGraphicsEllipseItem(data["v1"][0], data["v1"][1], data["r"], data["r"])
	o.setPos(0, 0)
	
	o.setStartAngle(int(data["start_ang"]*16))
	o.setSpanAngle(int(data["end_ang"]*16))

	#	OUTLINE
	pen = QPen(Qt.black)
	pen.setWidth(1)
	o.setPen(pen)
	
	#	SET DATA
	o.setData(0, data)
	
	#	SET FLAGS
	o.setFlag(QGraphicsItem.ItemIsMovable)
	o.setFlag(QGraphicsItem.ItemIsSelectable)
	o.setFlag(QGraphicsItem.ItemIsFocusable)
	
	self.scene.addItem(o)
Thankyou
Reply
#2
So... I went about it like this but I clearly don't understand how arcTo() works, I keep getting a leading line???

The following I get from reading a DXF file:
{'type': 'ARC', 'pos': [0, 0], 'layer': 'What', 'r': 30.0, 'start_ang': 180.0, 'end_ang': 315.0, 'v1': [30.0, 70.0, 0]}
* BTW: Ignore the pos, the real centre point is v1


Whilst posting I've even just tried calculating the cos / sin offset, but no...

Anyway, here's my code if anyone can explain how drawing the afore-mentioned arc is achieved.


import sys
from PyQt5.QtCore import Qt, QRectF
from PyQt5.QtGui import QBrush, QPainter, QPen, QTransform, QPainterPath
from PyQt5.QtWidgets import (
	QApplication,
	QMainWindow,
	QWidget,
	QGraphicsScene,
	QGraphicsView,
	QHBoxLayout,
	QVBoxLayout,
	QPushButton,
	QGraphicsItem,
	QGraphicsLineItem,
	QGraphicsPathItem
)

class Win(QMainWindow):
	
	view_scales = [0.2, 0.4, 0.6, 0.8, 1.0, 1.5, 2.0, 3.0]
	view_scale_current = 4
	
	def __init__(self):
		super().__init__()
		
		#	GRAPHICS SCENE & VIEW
		self.scene = QGraphicsScene(0, 0, 2400, 2400)
		self.view = QGraphicsView(self.scene)
		self.view.setRenderHint(QPainter.Antialiasing)
		
		#	TEST TOOLBAR
		toolbox = QHBoxLayout()
		
		btn_all = QPushButton("ALL")
		btn_all.clicked.connect(self.view_scale_all)
		toolbox.addWidget(btn_all)
		
		#	MAIN LAYOUT
		vbox = QVBoxLayout()
		vbox.addWidget(self.view)
		vbox.addLayout(toolbox)
		
		#	WINDOW LAYOUT
		widget = QWidget()
		widget.setLayout(vbox)
		self.setCentralWidget(widget)
		
		#	LOAD DRAWING
		self.dwg_load()
	
	def dwg_load(self):
		#	TMP
		#self.item_add_line({"pos":[0, 0], "v1":[10, 10], "v2":[100, 10]})
		#self.item_add_line({"pos":[0, 0], "v1":[10, 20], "v2":[100, 100]})
		#self.item_add_line({"pos":[150, 50], "v1":[0, 0], "v2":[100, 100]})
		
		self.item_add_poly({"pos":[0, 0], "v":[[10,10], [50, 80], [60, 80], [60, 100], [80, 120]]})
		self.item_add_arc({'type': 'ARC', 'pos': [0, 0], 'layer': 'What', 'r': 30.0, 'start_ang': 180.0, 'end_ang': 315.0, 'v1': [30.0, 70.0, 0]})
		
	def item_add_arc(self, data):
		path = QPainterPath()
		
		#path.moveTo(pline[0][0], pline[0][1])
		#path.moveTo(data["v1"][0], data["v1"][1])
		path.moveTo(data["v1"][0]-data["r"], data["v1"][1]-data["r"])
		
		#QPainterPath::arcTo(qreal x, qreal y, qreal width, qreal height, qreal startAngle, qreal sweepLength)
		#path.arcTo(data["v1"][0], data["v1"][1], data["r"], data["r"], data["start_ang"], data["end_ang"]-data["start_ang"])
		path.arcTo(data["v1"][0], data["v1"][1], data["r"]*2, data["r"]*2, data["start_ang"], data["start_ang"]-data["end_ang"])
		
		o = QGraphicsPathItem(path)
		o.setPos(data["pos"][0], data["pos"][1])
		
		#	OUTLINE
		pen = QPen(Qt.red)
		pen.setWidth(1)
		o.setPen(pen)
		
		#	SET DATA
		o.setData(0, data)
		
		#	PROPERTIES
		o.setFlag(QGraphicsItem.ItemIsMovable)
		o.setFlag(QGraphicsItem.ItemIsSelectable)
		
		#	ADD
		self.scene.addItem(o)
		
	def item_add_poly(self, data):
		path = QPainterPath()
		
		pline = data["v"]
		
		path.moveTo(pline[0][0], pline[0][1])
		for i in range(1, len(pline)):
			path.lineTo(pline[i][0], pline[i][1])
				
		o = QGraphicsPathItem(path)
		o.setPos(data["pos"][0], data["pos"][1])
		
		#	OUTLINE
		pen = QPen(Qt.red)
		pen.setWidth(1)
		o.setPen(pen)
		
		#	SET DATA
		o.setData(0, data)
		
		#	PROPERTIES
		o.setFlag(QGraphicsItem.ItemIsMovable)
		o.setFlag(QGraphicsItem.ItemIsSelectable)
		
		#	ADD
		self.scene.addItem(o)
		
		
	def item_add_line(self, data):
		
		# Draw a rectangle item, setting the dimensions.
		o = QGraphicsLineItem()	#0, 0, 200, 50)
		o.setPos(data["pos"][0], data["pos"][1])
		o.setLine(data["v1"][0], data["v1"][1], data["v2"][0], data["v2"][1])
		
		#	OUTLINE
		pen = QPen(Qt.red)
		pen.setWidth(1)
		o.setPen(pen)
		
		#	SET DATA
		o.setData(0, data)
		
		#	PROPERTIES
		o.setFlag(QGraphicsItem.ItemIsMovable)
		o.setFlag(QGraphicsItem.ItemIsSelectable)
		
		#	ADD
		self.scene.addItem(o)
		
	def view_scale_all(self):
		print("ZOOM ALL")
		items = self.scene.items()
		
		#	CALC BOUNDS
		min_x = sys.float_info.max
		max_x = sys.float_info.min
		min_y = sys.float_info.max
		max_y = sys.float_info.min
		#i = 0
		for item in items:
			d = item.data(0)
			if d != None:
				br = item.sceneBoundingRect()
				#br = item.childrenBoundingRect()
				br.translate(item.pos())
				
				#	TOP LEFT
				if br.left() < min_x:
					min_x = br.left()
				
				if br.top() < min_y:
					min_y = br.top()
				
				#	BOTTOM RIGHT
				if br.right() > max_x:
					max_x = br.right()
				
				if br.bottom() > max_y:
					max_y = br.bottom()
				
		max_x -= min_x
		max_y -= min_y
		
		self.view.fitInView(QRectF(min_x, min_y, max_x, max_y), Qt.KeepAspectRatio)
		self.view.repaint()
		
if __name__ == '__main__':
	app = QApplication(sys.argv)
	w = Win()
	w.show()
	sys.exit(app.exec_())
Thanks
Reply
#3
Just found another image in some docs, so here is my failing code that tried to start at the start of the arc...
		path.moveTo(data["v1"][0]-data["r"], data["v1"][1]-data["r"])
	
		px = data["v1"][0] + (math.cos(data["start_ang"]) * data["r"])
		py = data["v1"][1] + (math.sin(data["start_ang"]) * data["r"])
		
		path.arcTo(px, py, data["r"]*2, data["r"]*2, data["start_ang"], data["start_ang"]-data["end_ang"])
Any ideas please?
Reply
#4
grrrr, nope
		px = data["v1"][0] + (math.cos(data["start_ang"]) * data["r"])
		py = data["v1"][1] + (math.sin(data["start_ang"]) * data["r"])
		
		path.moveTo(px, py)
		
		path.arcTo(data["v1"][0], data["v1"][1], data["r"]*2, data["r"]*2, data["start_ang"], data["start_ang"]-data["end_ang"])
Reply
#5
I'll do some real world tests tomorrow but it'll do for now...

	def item_add_arc2(self, data):
		path = QPainterPath()
	
		resolution = 12
		
		pline = []
		
		ang = (data["end_ang"] - data["start_ang"]) / resolution
		#print("ANG:", ang)
		
		for i in range(resolution):
			pline.append([
				data["v1"][0]+(math.cos(math.radians(data["start_ang"]+(i*ang))) * data["r"]), 
				data["v1"][1]+(math.sin(math.radians(data["start_ang"]+(i*ang))) * data["r"])
				])
		
		path.moveTo(pline[0][0], pline[0][1])
		for i in range(1, len(pline)):
			path.lineTo(pline[i][0], pline[i][1])
				
		o = QGraphicsPathItem(path)
		o.setPos(data["pos"][0], data["pos"][1])
		
		#	OUTLINE
		pen = QPen(Qt.red)
		pen.setWidth(1)
		o.setPen(pen)
		
		#	SET DATA
		o.setData(0, data)
		
		#	PROPERTIES
		o.setFlag(QGraphicsItem.ItemIsMovable)
		o.setFlag(QGraphicsItem.ItemIsSelectable)
		
		#	ADD
		self.scene.addItem(o)
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020