Skip to content

Commit

Permalink
Update Readme
Browse files Browse the repository at this point in the history
  • Loading branch information
mkondratyev85 committed Oct 14, 2020
1 parent 757f1c7 commit af07f84
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 10 deletions.
49 changes: 48 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,49 @@
# pattern_definition_editor
GUI editor for pattern definition files in ezdxf format

This is a simple editor for pattern definitions that
could be used by `ezdxf` library to create custom
pattern definition to fill polygons.

![](gui.png)

Select line to edit by hitting 'Select Line' and then clicking on the desire line.

By moving rectangular control anchors you can change origin point of the line, its angle, offset.

If you want selected line to has dashed pattern click 'Add Dash to Line' it will make
line 'dashed' and it will also add another one control anchor.

It saves pattern definition as lists via `pickle` module. You can open saved files to edit them later.
Or, you can use them in `ezdxf` like this:

``` python
import pickle

import ezdxf

# load pattern definition from file
filename = '/tmp/pd.pickle'
with open(filename, 'rb') as f:
pattern_definition = pickle.load(f)

doc = ezdxf.new('R2010')
msp = doc.modelspace()
hatch = msp.add_hatch()
hatch.set_pattern_fill('MY_PATTERN',
definition=pattern_definition,
scale=0.01
)
hatch.paths.add_polyline_path(
[(0, 0), (0, 3), (3, 6), (6, 6), (6, 3), (3, 0)],
)
doc.saveas('/tmp/example.dxf') # save DXF drawing
```

This will produce hatched pattern that is supported at least by AutoCad and QCad:

![](cad.png)


## Requirements

python3.9
Binary file added cad.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import pickle

import ezdxf

# load pattern definition from file
filename = '/tmp/pd.pickle'
with open(filename, 'rb') as f:
pattern_definition = pickle.load(f)

doc = ezdxf.new('R2010')
msp = doc.modelspace()
hatch = msp.add_hatch() # by default a SOLID fill
hatch.set_pattern_fill('MY_PATTERN',
definition=pattern_definition,
scale=0.01
)
hatch.paths.add_polyline_path(
[(0, 0), (0, 3), (3, 6), (6, 6), (6, 3), (3, 0)],
)
doc.saveas(f"/tmp/example.dxf") # save DXF drawing
Binary file added gui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
63 changes: 54 additions & 9 deletions model.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ def from_list_to_lines(self, list_):

def save_pattern(self, filename):
lines = self.get_list_of_lines()
with open(filename, 'wb') as f:
pickle.dump(lines, f)
with open(filename, 'wb') as f: pickle.dump(lines, f)

def open_pattern(self, filename):
with open(filename, 'rb') as f:
Expand All @@ -67,35 +66,81 @@ class Line:
canvas_line_id: Optional[int] = None

@property
def length(self) -> float:
def length2nd(self) -> float:
'''
Returns length of solid segment in line
(length to 2nd point)
'''
return 100
if self.dash_length_items:
return self.dash_length_items[0]
else:
return 100

@property
def length3nd(self) -> float:
'''
Returns length of solid segment plus dashed segment in line
(length to 3nd point)
If line is solid - return length to second
'''
if self.dash_length_items:
return self.dash_length_items[0] - self.dash_length_items[1]
else:
return self.length2nd

def add_dash(self) -> None:
'''
Adds dash element to the line.
'''
self.dash_length_items = [self.length2nd, -self.length2nd]

@property
def second_point(self) -> Tuple[float, float]:
'''
Returns second point from base_point
'''
x0, y0 = self.base_point
x1 = x0 + self.length * math.cos(math.radians(self.angle))
y1 = y0 + self.length * math.sin(math.radians(self.angle))
x1 = x0 + self.length2nd * math.cos(math.radians(self.angle))
y1 = y0 + self.length2nd * math.sin(math.radians(self.angle))
return x1, y1

@property
def third_point(self) ->Optional[Tuple[float, float]]:
'''
Returns thrid point (representing dash).
'''
x0, y0 = self.base_point
x2 = x0 + self.length3nd * math.cos(math.radians(self.angle))
y2 = y0 + self.length3nd * math.sin(math.radians(self.angle))
return x2, y2

def update_2nd_point(self, x1: float, y1: float) -> None:
'''
Updates angle and dash_length_items based of 2nd point
'''
x0, y0 = self.base_point
self.angle = math.degrees(math.atan2((y1 - y0), (x1 - x0)))
if self.dash_length_items:
length = math.sqrt((x1-x0)**2 + (y1-y0)**2)
self.dash_length_items[0] = length

def update_3nd_point(self, x1: float, y1: float) -> None:
'''
Updates dash_length_items based of 3nd point
'''
if self.dash_length_items:
x0, y0 = self.base_point
length = math.sqrt((x1-x0)**2 + (y1-y0)**2)
length_ = length - self.dash_length_items[0]
self.dash_length_items[1] = -length_


def get_many_lines(self):
'''
Yields coordinates of lines that could be drawn from self
'''

for i in range(-5, 5, 1):
for i in range(-15, 15, 1):
x0, y0 = self.base_point
dx, dy = self.offset
x0 += i*dx
Expand All @@ -105,9 +150,9 @@ def get_many_lines(self):
angle=self.angle,
dash_length_items=self.dash_length_items,
)
for j in range(-5, 5, 1):
for j in range(-15, 15, 1):
x0, y0 = new_line.base_point
x1, y1 = new_line.second_point
x1, y1 = new_line.third_point
dx, dy = x1-x0, y1-y0
x0 += j*dx
y0 += j*dy
Expand Down
2 changes: 2 additions & 0 deletions sidepanel.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ def __init__(self, root):
self.SelectLIneButton.pack(side="top", fill=tk.BOTH)
self.AddLIneButton = tk.Button(self.frame2, text="Add Line")
self.AddLIneButton.pack(side="top", fill=tk.BOTH)
self.AddDashButton = tk.Button(self.frame2, text="Add Dash to Line")
self.AddDashButton.pack(side="top", fill=tk.BOTH)
self.RemoveLIneButton = tk.Button(self.frame2, text="Remove Selected Line")
self.RemoveLIneButton.pack(side="top", fill=tk.BOTH)
self.SaveButton = tk.Button(self.frame2, text="Save Pattern")
Expand Down
20 changes: 20 additions & 0 deletions view.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
MOVE_BASE_POINT = 1
MOVE_SECOND_POINT = 2
MOVE_OFFSET_POINT = 3
MOVE_THIRD_POINT = 4

class View:
def __init__(self, root, model):
Expand All @@ -26,6 +27,7 @@ def __init__(self, root, model):
self.sidepanel.RemoveLIneButton.bind("<Button>", self._remove_selected_line)
self.sidepanel.SaveButton.bind("<Button>", self._save)
self.sidepanel.OpenButton.bind("<Button>", self._open)
self.sidepanel.AddDashButton.bind('<Button>', self._add_dash)

self.canvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)

Expand All @@ -38,6 +40,11 @@ def __init__(self, root, model):

self.draw_lines(None)

def _add_dash(self, event):
line = self.get_line_by_object_id(self.selected_line_id)
line.add_dash()
self.redraw_line(self.selected_line_id)

def _open(self, event):
filename = filedialog.askopenfile(mode='r', defaultextension='.pickle')
if filename is None:
Expand Down Expand Up @@ -83,6 +90,8 @@ def on_motion(self, event):
elif self.mode == MOVE_OFFSET_POINT:
x0, y0 = line.base_point
line.offset = (x-x0, y-y0)
elif self.mode == MOVE_THIRD_POINT:
line.update_3nd_point(x, y)

self.redraw_line(self.selected_line_id)

Expand All @@ -103,6 +112,8 @@ def on_line_click(self, event):
self.mode = MOVE_SECOND_POINT
elif self.offset_point_anchor_id in clicked_object_ids:
self.mode = MOVE_OFFSET_POINT
elif self.third_point_anchor_id in clicked_object_ids:
self.mode = MOVE_THIRD_POINT


def draw_lines(self, event):
Expand Down Expand Up @@ -136,20 +147,29 @@ def draw_anchors(self, line_id, new=False):
x1, y1 = line.second_point
dx, dy = line.offset
xo, yo = x0+dx, y0+dy
x3, y3 = line.third_point
base_coords = (x0-RW, y0-RW, x0+RW, y0+RW)
second_coords = (x1-2*RW, y1-RW, x1+2*RW, y1+RW)
offset_coords = (xo-RW, yo-RW, xo+RW, yo+RW)
if line.dash_length_items:
third_coords = (x3-RW, y3-RW, x3+RW, y3+RW)
else:
# in case we have a solid line we shift third point far beyond screen
third_coords = -10,-10,-10,-10
if new:
id = self.canvas.create_rectangle(*base_coords)
self.base_point_anchor_id = id
id = self.canvas.create_rectangle(*second_coords)
self.second_point_anchor_id = id
id = self.canvas.create_rectangle(*offset_coords)
self.offset_point_anchor_id = id
id = self.canvas.create_rectangle(*third_coords)
self.third_point_anchor_id = id
else:
self.canvas.coords(self.base_point_anchor_id, base_coords)
self.canvas.coords(self.second_point_anchor_id, second_coords)
self.canvas.coords(self.offset_point_anchor_id, offset_coords)
self.canvas.coords(self.third_point_anchor_id, third_coords)



0 comments on commit af07f84

Please sign in to comment.