Skip to content

Commit

Permalink
Center heated bed when frame is selected
Browse files Browse the repository at this point in the history
  • Loading branch information
gbroques committed Feb 13, 2020
1 parent 0df3550 commit a3d3adc
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 123 deletions.
38 changes: 9 additions & 29 deletions ose3dprinter/core/face_orientation.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from FreeCAD import Console, Vector
from FreeCAD import Console

from .enums import AxisOrientation, Side
from .get_outer_faces_of_frame import get_outer_faces_of_frame
from .is_face_parallel_to_plane import (is_face_parallel_to_xy_plane,
is_face_parallel_to_xz_plane,
is_face_parallel_to_yz_plane)


def get_face_closest_to_origin(frame, axis_orientation):
Expand Down Expand Up @@ -49,11 +52,6 @@ def get_orientation_of_attachable_axis(face):
return None


def get_is_face_parallel_to_plane(axis_orientation):
d = get_is_face_parallel_to_plane_by_axis_orientation()
return d[axis_orientation]


def get_is_face_parallel_to_plane_by_axis_orientation():
return {
AxisOrientation.X: is_face_parallel_to_xy_plane,
Expand All @@ -62,6 +60,11 @@ def get_is_face_parallel_to_plane_by_axis_orientation():
}


def get_is_face_parallel_to_plane(axis_orientation):
d = get_is_face_parallel_to_plane_by_axis_orientation()
return d[axis_orientation]


def get_face_side(frame, face):
attachable_axis_orientation = get_orientation_of_attachable_axis(face)
if attachable_axis_orientation is None:
Expand All @@ -82,26 +85,3 @@ def get_sides_by_axis_orientation():
AxisOrientation.Y: (Side.LEFT, Side.RIGHT),
AxisOrientation.Z: (Side.FRONT, Side.REAR)
}


def is_face_parallel_to_yz_plane(face):
x_axis = Vector(1, 0, 0)
return is_face_parallel_to_plane(face, x_axis)


def is_face_parallel_to_xz_plane(face):
y_axis = Vector(0, 1, 0)
return is_face_parallel_to_plane(face, y_axis)


def is_face_parallel_to_xy_plane(face):
z_axis = Vector(0, 0, 1)
return is_face_parallel_to_plane(face, z_axis)


def is_face_parallel_to_plane(face, axis_vector):
return axis_vector == Vector(
abs(round(face.Surface.Axis.x)),
abs(round(face.Surface.Axis.y)),
abs(round(face.Surface.Axis.z))
)
13 changes: 13 additions & 0 deletions ose3dprinter/core/get_heated_bed_frame_centered_kwargs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from FreeCAD import Placement, Vector, Rotation


def get_heated_bed_frame_centered_kwargs(frame):
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)
return {
'placement': placement,
'origin_translation_offset': origin_translation_offset
}
26 changes: 26 additions & 0 deletions ose3dprinter/core/is_edge_parallel_to_axis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
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}
inverse_orientations = filter(
lambda item: item[0] != axis, index_by_axis.items())
a_index, b_index = map(lambda item: item[1], inverse_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
24 changes: 24 additions & 0 deletions ose3dprinter/core/is_face_parallel_to_plane.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from FreeCAD import Vector


def is_face_parallel_to_yz_plane(face):
x_axis = Vector(1, 0, 0)
return is_face_parallel_to_plane(face, x_axis)


def is_face_parallel_to_xz_plane(face):
y_axis = Vector(0, 1, 0)
return is_face_parallel_to_plane(face, y_axis)


def is_face_parallel_to_xy_plane(face):
z_axis = Vector(0, 0, 1)
return is_face_parallel_to_plane(face, z_axis)


def is_face_parallel_to_plane(face, axis_vector):
return axis_vector == Vector(
abs(round(face.Surface.Axis.x)),
abs(round(face.Surface.Axis.y)),
abs(round(face.Surface.Axis.z))
)
88 changes: 88 additions & 0 deletions ose3dprinter/core/model/base_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from math import degrees

import Part
from FreeCAD import Console, Vector
from ose3dprinter.core.is_edge_parallel_to_axis import (
is_edge_parallel_to_x_axis, is_edge_parallel_to_y_axis,
is_edge_parallel_to_z_axis)


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 move_part(self, part, 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

part.translate(origin)
part.rotate(origin, rotation.Axis, degrees(rotation.Angle))


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_edges_connected_to_vertex(
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
)


def get_edges_connected_to_vertex(vertex, edges):
vertex_edges = []
for e in edges:
for v in e.Vertexes:
if v.isSame(vertex):
vertex_edges.append(e)
return vertex_edges
22 changes: 15 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,14 @@ 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) # 50.8 mm = 2 inches
bed = Part.makeBox(*dimensions)

parts = [bed]
self.move_parts(parts, dimensions)

# TODO: Why does this need to be a compound to visually center heated bed?
obj.Shape = Part.makeCompound(parts)

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

import Part
from FreeCAD import Vector, Console
from FreeCAD import Vector
from ose3dprinter.core.is_edge_parallel_to_axis import \
is_edge_parallel_to_z_axis
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 +19,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 +125,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 @@ -142,71 +137,3 @@ def __getstate__(self):
def __setstate__(self, state):
if 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')


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
)
Loading

0 comments on commit a3d3adc

Please sign in to comment.