Skip to content

Commit

Permalink
Center heated bed when frame is selected (work in progress)
Browse files Browse the repository at this point in the history
  • Loading branch information
gbroques committed Feb 12, 2020
1 parent 0df3550 commit 4e5743a
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 74 deletions.
101 changes: 101 additions & 0 deletions ose3dprinter/core/model/base_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
from math import degrees

import Part
from FreeCAD import Vector, Console


class BaseModel(object):
"""
Base class for models that encapsulate the data (i.e. topography and shape)
for a part, and is separate from the "view" or GUI representation.
"""

def __init__(self, placement, origin_translation_offset):
"""
Constructor
Arguments
---------
- obj: Created with document.addObject('Part::FeaturePython', '{name}')
"""
self.placement = placement
self.origin_translation_offset = origin_translation_offset

def move_parts(self, parts, reference_dimensions):
base = self.placement.Base
rotation = self.placement.Rotation

translation_offset = get_translation_offset(
reference_dimensions, rotation, self.origin_translation_offset)
origin = base - translation_offset
for part in parts:
part.translate(origin)
part.rotate(origin, rotation.Axis, degrees(rotation.Angle))


def is_edge_parallel_to_x_axis(edge):
return is_edge_parallel_to_axis(edge, 'x')


def is_edge_parallel_to_y_axis(edge):
return is_edge_parallel_to_axis(edge, 'y')


def is_edge_parallel_to_z_axis(edge):
return is_edge_parallel_to_axis(edge, 'z')


def is_edge_parallel_to_axis(edge, axis):
index_by_axis = {'x': 0, 'y': 1, 'z': 2}
opposite_orientations = filter(
lambda item: item[0] != axis, index_by_axis.items())
a_index, b_index = map(lambda item: item[1], opposite_orientations)
first_point = edge.valueAt(edge.FirstParameter)
a1 = round(first_point[a_index])
b1 = round(first_point[b_index])

last_point = edge.valueAt(edge.LastParameter)
a2 = round(last_point[a_index])
b2 = round(last_point[b_index])

return a1 == a2 and b1 == b2


def get_vertex_edges(vertex, edges):
vertex_edges = []
for e in edges:
for v in e.Vertexes:
if v.isSame(vertex):
vertex_edges.append(e)
return vertex_edges


def get_translation_offset(reference_dimensions,
rotation,
origin_translation_offset):
reference_box = Part.makeBox(*reference_dimensions)
reference_box.rotate(Vector(0, 0, 0), rotation.Axis,
degrees(rotation.Angle))
first_vertex = reference_box.Vertexes[0]
first_vertex_edges = get_vertex_edges(first_vertex, reference_box.Edges)
num_edges = len(first_vertex_edges)
if num_edges != 3:
Console.PrintWarning(
'Found {} edges connected to cube vertex instead of 3.\n'.format(num_edges))
x = y = z = 1.0
for e in first_vertex_edges:
if is_edge_parallel_to_x_axis(e):
x = e.Length
elif is_edge_parallel_to_y_axis(e):
y = e.Length
elif is_edge_parallel_to_z_axis(e):
z = e.Length
else:
Console.PrintWarning(
'{} not parallel to x, y, or z axes\n'.format(e))

return Vector(
x * origin_translation_offset.x,
y * origin_translation_offset.y,
z * origin_translation_offset.z
)
23 changes: 16 additions & 7 deletions ose3dprinter/core/model/heated_bed/heated_bed_model.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import Part
from FreeCAD import Base
from ose3dprinter.core.model.base_model import BaseModel


class HeatedBedModel:
class HeatedBedModel(BaseModel):
"""
Encapsulates the data (i.e. topography and shape) for a Heated Bed,
and is separate from the "view" or GUI representation.
"""

def __init__(self, obj):
def __init__(self, obj, placement, origin_translation_offset):
"""
Constructor
Arguments
---------
- obj: Created with document.addObject('Part::FeaturePython', '{name}')
"""
self.Type = 'OSEUniversalAxis'
init_args = (placement, origin_translation_offset)
super(HeatedBedModel, self).__init__(*init_args)

self.Type = 'OSEHeatedBed'

obj.Proxy = self

Expand All @@ -30,9 +33,15 @@ def execute(self, obj):
Called on document recompute
"""
size = obj.Size.Value
bed = Part.makeBox(size, size, 50.8) # 50.8 mm = 2 inches
bed.rotate(Base.Vector(0, 0, 0), Base.Vector(0, -1, 0), 90)
obj.Shape = bed
dimensions = (size, size, 50.8)
bed = Part.makeBox(*dimensions) # 50.8 mm = 2 inches

# TODO: Why does this need to be an array of parts
# and compound to work?
parts = [bed]
self.move_parts(parts, dimensions)

obj.Shape = Part.makeCompound(parts)

def __getstate__(self):
return self.Type
Expand Down
75 changes: 12 additions & 63 deletions ose3dprinter/core/model/universal_axis/universal_axis_model.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from math import degrees

import Part
from FreeCAD import Vector, Console
from FreeCAD import Vector
from ose3dprinter.core.model.base_model import BaseModel


class UniversalAxisModel:
class UniversalAxisModel(BaseModel):
"""
Encapsulates the data (i.e. topography and shape) for a Universal Axis,
and is separate from the "view" or GUI representation.
Expand All @@ -18,9 +17,10 @@ def __init__(self, obj, length, placement, origin_translation_offset):
---------
- obj: Created with document.addObject('Part::FeaturePython', '{name}')
"""
init_args = (placement, origin_translation_offset)
super(UniversalAxisModel, self).__init__(*init_args)

self.Type = 'OSEUniversalAxis'
self.placement = placement
self.origin_translation_offset = origin_translation_offset

obj.Proxy = self

Expand Down Expand Up @@ -123,16 +123,9 @@ def execute(self, obj):
rod2
]

base = self.placement.Base
rotation = self.placement.Rotation

reference_dimensions = (rod_length, motor_box_length, box_height)
translation_offset = get_translation_offset(
reference_dimensions, rotation, self.origin_translation_offset)
origin = base - translation_offset
for part in parts:
part.translate(origin)
part.rotate(origin, rotation.Axis, degrees(rotation.Angle))
self.move_parts(parts, reference_dimensions)

compound = Part.makeCompound(parts)
obj.Shape = compound

Expand All @@ -144,18 +137,14 @@ def __setstate__(self, state):
self.Type = state


def is_edge_parallel_to_x_axis(edge):
return is_edge_parallel_to_axis(edge, 'x')


def is_edge_parallel_to_y_axis(edge):
return is_edge_parallel_to_axis(edge, 'y')


# TODO: Function leaves in base_model
# Remove duplication
def is_edge_parallel_to_z_axis(edge):
return is_edge_parallel_to_axis(edge, 'z')


# TODO: Function leaves in base_model
# Remove duplication
def is_edge_parallel_to_axis(edge, axis):
index_by_axis = {'x': 0, 'y': 1, 'z': 2}
opposite_orientations = filter(
Expand All @@ -170,43 +159,3 @@ def is_edge_parallel_to_axis(edge, axis):
b2 = round(last_point[b_index])

return a1 == a2 and b1 == b2


def get_vertex_edges(vertex, edges):
vertex_edges = []
for e in edges:
for v in e.Vertexes:
if v.isSame(vertex):
vertex_edges.append(e)
return vertex_edges


def get_translation_offset(reference_dimensions,
rotation,
origin_translation_offset):
reference_box = Part.makeBox(*reference_dimensions)
reference_box.rotate(Vector(0, 0, 0), rotation.Axis,
degrees(rotation.Angle))
first_vertex = reference_box.Vertexes[0]
first_vertex_edges = get_vertex_edges(first_vertex, reference_box.Edges)
num_edges = len(first_vertex_edges)
if num_edges != 3:
Console.PrintWarning(
'Found {} edges connected to cube vertex instead of 3.\n'.format(num_edges))
x = y = z = 1.0
for e in first_vertex_edges:
if is_edge_parallel_to_x_axis(e):
x = e.Length
elif is_edge_parallel_to_y_axis(e):
y = e.Length
elif is_edge_parallel_to_z_axis(e):
z = e.Length
else:
Console.PrintWarning(
'{} not parallel to x, y, or z axes\n'.format(e))

return Vector(
x * origin_translation_offset.x,
y * origin_translation_offset.y,
z * origin_translation_offset.z
)
17 changes: 16 additions & 1 deletion ose3dprinter/workbench/add_heated_bed.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import FreeCAD as App
import FreeCADGui as Gui
from ose3dprinter.workbench.part import create_heated_bed
from ose3dprinter.workbench.resources import get_resource_path
from FreeCAD import Placement, Vector, Rotation, Console


class AddHeatedBed:
Expand All @@ -14,7 +16,20 @@ def Activated(self):
document = App.ActiveDocument
if not document:
document = App.newDocument()
create_heated_bed(document, 'HeatedBed')
selection_objects = Gui.Selection.getSelectionEx()
creation_kwargs = {}
if len(selection_objects) > 0 and selection_objects[0].Object.Proxy.Type == 'OSEFrame':
frame = selection_objects[0].Object
half_frame_size = frame.Size / 2
z = frame.Placement.Base.z
placement = Placement(
Vector(half_frame_size, half_frame_size, z), Rotation())
origin_translation_offset = Vector(0.5, 0.5, 0)
creation_kwargs = {
'placement': placement,
'origin_translation_offset': origin_translation_offset
}
create_heated_bed(document, 'HeatedBed', **creation_kwargs)
document.recompute()

def IsActive(self):
Expand Down
11 changes: 8 additions & 3 deletions ose3dprinter/workbench/part/heated_bed/create_heated_bed.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
from FreeCAD import Placement, Vector
from ose3dprinter.core.model import HeatedBedModel


def create_heated_bed(document, name):
def create_heated_bed(document,
name,
placement=Placement(),
origin_translation_offset=Vector()):
"""
Creates a heated bed object with the given name,
and adds it to the document.
"""
obj = document.addObject('Part::FeaturePython', name)
HeatedBedModel(obj)
obj.ViewObject.Proxy = 0 # Mandatory unless ViewProvider is coded
HeatedBedModel(obj, placement, origin_translation_offset)
if obj.ViewObject is not None:
obj.ViewObject.Proxy = 0 # Mandatory unless ViewProvider is coded
return obj

0 comments on commit 4e5743a

Please sign in to comment.