Skip to content

Commit 4ed0f5c

Browse files
committed
Add settings to choose line clipping algo
1 parent 2e1c422 commit 4ed0f5c

File tree

5 files changed

+131
-12
lines changed

5 files changed

+131
-12
lines changed

data/main.ui

+9-2
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,8 @@
383383
<rect>
384384
<x>0</x>
385385
<y>0</y>
386-
<width>306</width>
387-
<height>226</height>
386+
<width>186</width>
387+
<height>163</height>
388388
</rect>
389389
</property>
390390
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0">
@@ -973,6 +973,8 @@
973973
<addaction name="actionSave"/>
974974
<addaction name="separator"/>
975975
<addaction name="actionNew"/>
976+
<addaction name="separator"/>
977+
<addaction name="actionSettings"/>
976978
</widget>
977979
<action name="actionSave">
978980
<property name="text">
@@ -989,6 +991,11 @@
989991
<string>New</string>
990992
</property>
991993
</action>
994+
<action name="actionSettings">
995+
<property name="text">
996+
<string>Settings</string>
997+
</property>
998+
</action>
992999
</widget>
9931000
<resources/>
9941001
<connections/>

data/settings.ui

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>SettingsDialog</class>
4+
<widget class="QDialog" name="SettingsDialog">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>256</width>
10+
<height>144</height>
11+
</rect>
12+
</property>
13+
<property name="windowTitle">
14+
<string>Settings</string>
15+
</property>
16+
<property name="windowIcon">
17+
<iconset theme="preferences-other">
18+
<normaloff>.</normaloff>.</iconset>
19+
</property>
20+
<property name="sizeGripEnabled">
21+
<bool>false</bool>
22+
</property>
23+
<layout class="QGridLayout" name="gridLayout">
24+
<property name="topMargin">
25+
<number>8</number>
26+
</property>
27+
<property name="rightMargin">
28+
<number>8</number>
29+
</property>
30+
<property name="bottomMargin">
31+
<number>6</number>
32+
</property>
33+
<property name="spacing">
34+
<number>8</number>
35+
</property>
36+
<item row="0" column="0">
37+
<widget class="QGroupBox" name="clipGroup">
38+
<property name="title">
39+
<string>Line Clipping Algorithm</string>
40+
</property>
41+
<layout class="QVBoxLayout" name="verticalLayout">
42+
<property name="spacing">
43+
<number>0</number>
44+
</property>
45+
<item>
46+
<widget class="QRadioButton" name="clipLBButton">
47+
<property name="text">
48+
<string>Liang-Barsky</string>
49+
</property>
50+
<property name="checked">
51+
<bool>true</bool>
52+
</property>
53+
</widget>
54+
</item>
55+
<item>
56+
<widget class="QRadioButton" name="clipCSButton">
57+
<property name="text">
58+
<string>Cohen-Sutherland</string>
59+
</property>
60+
<property name="checked">
61+
<bool>false</bool>
62+
</property>
63+
</widget>
64+
</item>
65+
</layout>
66+
</widget>
67+
</item>
68+
<item row="1" column="0">
69+
<widget class="QDialogButtonBox" name="buttonBox">
70+
<property name="standardButtons">
71+
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
72+
</property>
73+
<property name="centerButtons">
74+
<bool>true</bool>
75+
</property>
76+
</widget>
77+
</item>
78+
</layout>
79+
</widget>
80+
<resources/>
81+
<connections/>
82+
</ui>

pycg/app.py

+32-6
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
from typing import Optional, Callable, Dict, Sequence, Tuple
66
from ast import literal_eval
77

8-
from PySide2.QtWidgets import (QApplication, QMainWindow, QWidget, QColorDialog,
9-
QFileDialog, QMessageBox, QInputDialog)
8+
from PySide2.QtWidgets import (QApplication, QMainWindow, QWidget, QDialog,
9+
QColorDialog, QFileDialog, QMessageBox, QInputDialog)
1010
from PySide2.QtGui import (QPainter, QKeySequence, QColor, QPalette, QIcon,
1111
QPixmap, QPolygon)
1212
from PySide2.QtCore import Qt, QPoint
@@ -18,6 +18,7 @@
1818
import obj as wavefront_obj
1919
from ui.main import Ui_MainWindow
2020
from ui.point import Ui_PointFields
21+
from ui.settings import Ui_SettingsDialog
2122

2223

2324
class InteractiveGraphicalSystem(QMainWindow, Ui_MainWindow):
@@ -31,9 +32,9 @@ def log(message: str):
3132
else:
3233
print(message)
3334

34-
def __init__(self):
35+
def __init__(self, *args, **kwargs):
3536
# imported Qt UI setup
36-
super().__init__()
37+
QMainWindow.__init__(self, *args, **kwargs)
3738
self.setupUi(self)
3839

3940
self.display_file: Dict[str, Drawable] = dict()
@@ -126,6 +127,18 @@ def handle_new_action():
126127
if new_obj is not None:
127128
self.insert_object(new_obj, "object")
128129

130+
def handle_settings_action():
131+
dialog = SettingsDialog(self)
132+
cs = self.viewport.camera.line_clipping_algorithm == SettingsDialog.CLIP_CS
133+
dialog.clipLBButton.setChecked(not cs)
134+
dialog.clipCSButton.setChecked(cs)
135+
status = dialog.exec_()
136+
if status != QDialog.Accepted: return
137+
algo = (SettingsDialog.CLIP_CS if dialog.clipCSButton.isChecked()
138+
else SettingsDialog.CLIP_LB)
139+
self.viewport.camera.line_clipping_algorithm = algo
140+
self.log(f"Settings: line clipping algorithm set to '{algo}'.")
141+
129142
# setting up toolbar actions
130143
self.toolBar.setContextMenuPolicy(Qt.PreventContextMenu)
131144
self.actionSave.triggered.connect(handle_save_action)
@@ -134,6 +147,8 @@ def handle_new_action():
134147
self.actionLoad.setShortcut(QKeySequence.Open)
135148
self.actionNew.triggered.connect(handle_new_action)
136149
self.actionNew.setShortcut(QKeySequence.New)
150+
self.actionSettings.triggered.connect(handle_settings_action)
151+
self.actionSettings.setShortcut(QKeySequence.Preferences)
137152

138153
def new_type_select(index: int):
139154
# clean all fields after 'name', 'color' and 'type'
@@ -438,8 +453,8 @@ def mouseMoveEvent(self, event):
438453

439454

440455
class PointFields(QWidget, Ui_PointFields):
441-
def __init__(self):
442-
super().__init__()
456+
def __init__(self, *args, **kwargs):
457+
QWidget.__init__(self, *args, **kwargs)
443458
self.setupUi(self)
444459
self.xDoubleSpinBox.setRange(-inf, inf)
445460
self.yDoubleSpinBox.setRange(-inf, inf)
@@ -479,6 +494,17 @@ def set_active(self, active: bool):
479494
self.yDoubleSpinBox.setEnabled(active)
480495

481496

497+
class SettingsDialog(QDialog, Ui_SettingsDialog):
498+
CLIP_CS = 'Cohen-Sutherland'
499+
CLIP_LB = 'Liang-Barsky'
500+
501+
def __init__(self, *args, **kwargs):
502+
QDialog.__init__(self, *args, **kwargs)
503+
self.setupUi(self)
504+
self.buttonBox.accepted.connect(lambda: self.accept())
505+
self.buttonBox.rejected.connect(lambda: self.reject())
506+
507+
482508
if __name__ == '__main__':
483509
if '-h' in argv:
484510
print(f"Usage: {argv[0]} [<objfiles> ...] | -h")

pycg/graphics.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ def transform(self, transformations: Transformation, pivot: Point = None):
213213

214214
def center(self) -> Point:
215215
# to avoid overweighting repeated points, only average over unique ones
216-
points = set(self._points)
216+
points = set({(x, y) for x, y in self._points})
217217
average = Point(0, 0)
218218
for x, y in points:
219219
average += Point(x, y)
@@ -256,6 +256,7 @@ def __init__(self, painter: Painter, size: Vector, offset: Point = None):
256256
self._dirty = True
257257
self._world_to_view = None
258258
self._view_to_screen = None
259+
self.line_clipping_algorithm = 'Liang-Barsky'
259260

260261
def draw_pixel(self, x, y):
261262
self._recompute_matrixes()
@@ -268,8 +269,10 @@ def draw_line(self, xa, ya, xb, yb):
268269
self._recompute_matrixes()
269270
a = self._world_to_view @ Vector(xa, ya, 1)
270271
b = self._world_to_view @ Vector(xb, yb, 1)
271-
# TODO: let the user choose which method to use
272-
clipped = clip_line(a.x, a.y, b.x, b.y)
272+
clipper = (make_clipper(-1, +1, -1, +1)
273+
if self.line_clipping_algorithm == 'Cohen-Sutherland'
274+
else clip_line)
275+
clipped = clipper(a.x, a.y, b.x, b.y)
273276
if clipped:
274277
xa, ya, xb, yb = clipped
275278
a = self._view_to_screen @ Vector(xa, ya, 1)

pycg/tests/test_graphics.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ def test_transformations_center_pivot():
2020
rect = Polygon([Point(-1, 1), Point(1, 1), Point(1, -1), Point(-1, -1)])
2121
s = Transformation().scale(4, 3)
2222
rect.transform(s)
23-
upper_left, upper_right, lower_right, lower_left = rect
23+
upper_left, upper_right, lower_right, lower_left, close = rect
24+
assert close == upper_left
2425
assert upper_left == (-4, 3)
2526
assert upper_right == (4, 3)
2627
assert lower_right == (4, -3)

0 commit comments

Comments
 (0)