コード例 #1
0
ファイル: gcodesvg.py プロジェクト: sod4602/tcnc
    def _fix_intersections(self, path):
        """Collapse self-intersecting loops.
        """
        # See: https://en.wikipedia.org/wiki/Bentley-Ottmann_algorithm
        # for a more efficient sweepline method O(Nlog(N)).
        # This is the bonehead way: O(n**2), but it's fine for
        # reasonable path lengths...
        # See: winding numbers. intersecting loops should match
        # underlying toolpath winding.
        fixed_path = []
        skip_ahead = 0
        for i, line1 in enumerate(path):
            if i < skip_ahead:
                continue
            p = None
            for j, line2 in enumerate(path[(i + 2):]):
                p = line1.intersection(line2, segment=True)
                if p is not None:
                    geom.debug.draw_point(p, color='#ffc000')
                    fixed_path.append(geom.Line(line1.p1, p))
                    fixed_path.append(geom.Line(p, line2.p2))
                    skip_ahead = i + j + 3
                    break
#            fixed_path.append(line1)
            if p is None:
                fixed_path.append(line1)
        return fixed_path
コード例 #2
0
ファイル: gcodesvg.py プロジェクト: sod4602/tcnc
    def _make_outline_path(self, points):
        # Find all the adjacent tan line intersections
        if len(self.toolmarks) > 1:
            prev_line = self.toolmarks[0]
            for next_line in self.toolmarks[1:]:
                p = prev_line.intersection(next_line)
                if p is not None:
                    geom.debug.draw_point(p, color="#ff0000")
                prev_line = next_line
        path = []
        if len(points) > 1:
            prev_pt = points[0]
            for next_pt in points[1:]:
                if next_pt != prev_pt:
                    # Simplify the outline by skipping inline nodes.
                    if path and path[-1].which_side(next_pt, inline=True) == 0:
                        prev_line = path.pop()
                        next_line = geom.Line(prev_line.p1, next_pt)
                    else:
                        next_line = geom.Line(prev_pt, next_pt)
#                    next_line = geom.Line(prev_pt, next_pt)
                    path.append(next_line)
                prev_pt = next_pt
            path = self._fix_intersections(path)
            path = self._fix_reversals(path)
        return path
コード例 #3
0
ファイル: geomsvg.py プロジェクト: sod4602/tcnc
def convert_rect(element):
    """Convert an SVG rect shape element to four geom.Line segments.

    Args:
        element: An SVG 'rect' element of the form
            <rect x='X' y='Y' width='W' height='H'/>

    Returns:
        A clockwise wound polygon as a list of geom.Line segments.
    """
    # Convert to a clockwise wound polygon
    x1 = float(element.get('x', 0))
    y1 = float(element.get('y', 0))
    x2 = x1 + float(element.get('width', 0))
    y2 = y1 + float(element.get('height', 0))
    p1 = (x1, y1)
    p2 = (x1, y2)
    p3 = (x2, y2)
    p4 = (x2, y1)
    return [
        geom.Line(p1, p2),
        geom.Line(p2, p3),
        geom.Line(p3, p4),
        geom.Line(p4, p1)
    ]
コード例 #4
0
ファイル: paintcam.py プロジェクト: sod4602/tcnc
    def process_brush_path(self, path):
        """
        """
        start_angle = util.seg_start_angle(path[0])
        # First prepend the landing strip if any.
        strip_dist = self.brush_landing_strip
        if strip_dist > self.gc.tolerance:
            delta = geom.P.from_polar(strip_dist, start_angle + math.pi)
            segment = geom.Line(path[0].p1 + delta, path[0].p1)
            if hasattr(path[0], 'inline_start_angle'):
                segment.inline_end_angle = path[0].inline_start_angle
            path.insert(0, segment)
        # Then prepend the soft landing segment.
        landing_dist = self.tool_trail_offset
        if self.brush_soft_landing and landing_dist > self.gc.tolerance:
            delta = geom.P.from_polar(landing_dist, start_angle + math.pi)
            segment = geom.Line(path[0].p1 + delta, path[0].p1)
            if hasattr(path[0], 'inline_start_angle'):
                segment.inline_end_angle = path[0].inline_start_angle
            path.insert(0, segment)
            #         d = max(self.tool_trail_offset, 0.01)
            #         if first_segment.length() > d:
            #             # If the segment is longer than the brush trail
            #             # cut it into two segments and use the first as the landing.
            #             seg1, seg2 = first_segment.subdivide(d / first_segment.length())
            #             path[0] = seg1
            #             path.insert(1, seg2)
            path[0].inline_z = self.z_step

        # Append overshoot segments if brush overshoot is enabled
        if self.brush_overshoot_enable:
            if self.brush_overshoot_auto:
                overshoot_dist = self.tool_width / 2
            else:
                overshoot_dist = self.brush_overshoot_distance
#             logger.debug('tw=%f, od=%f' % (self.tool_width, overshoot_dist))
            segment = path[-1]
            brush_direction = util.seg_end_angle(segment)
            if overshoot_dist > self.gc.tolerance:
                delta = geom.P.from_polar(overshoot_dist, brush_direction)
                overshoot_endp = segment.p2 + delta
                overshoot_line = geom.Line(segment.p2, overshoot_endp)
                path.append(overshoot_line)
            if self.brush_soft_landing:
                liftoff_dist = self.tool_trail_offset
                if liftoff_dist > self.gc.tolerance:
                    delta = geom.P.from_polar(liftoff_dist, brush_direction)
                    liftoff_endp = overshoot_endp + delta
                    liftoff_line = geom.Line(overshoot_endp, liftoff_endp)
                    liftoff_line.inline_z = 0.0
                    path.append(liftoff_line)
        return path
コード例 #5
0
 def _get_polygon_rays(self, vertices, clip_rect):
     """Return rays that emanate from convex vertices to the outside
     clipping rectangle.
     """
     rays = []
     for A, B, C in vertices:
         # Calculate the interior angle bisector segment
         # using the angle bisector theorem:
         # https://en.wikipedia.org/wiki/Angle_bisector_theorem
         AC = geom.Line(A, C)
         d1 = B.distance(C)
         d2 = B.distance(A)
         mu = d2 / (d1 + d2)
         D = AC.point_at(mu)
         bisector = geom.Line(D, B)
         # find the intersection with the clip rectangle
         dx = bisector.p2.x - bisector.p1.x
         dy = bisector.p2.y - bisector.p1.y
         # if dx is zero the line is vertical
         if geom.float_eq(dx, 0.0):
             y = clip_rect.ymax if dy > 0 else clip_rect.ymin
             x = bisector.p1.x
         else:
             # if slope is zero the line is horizontal
             m = dy / dx
             b = (m * -bisector.p1.x) + bisector.p1.y
             if dx > 0:
                 if geom.float_eq(m, 0.0):
                     y = b
                     x = clip_rect.xmax
                 else:
                     y = clip_rect.xmax * m + b
                     if m > 0:
                         y = min(clip_rect.ymax, y)
                     else:
                         y = max(clip_rect.ymin, y)
                     x = (y - b) / m
             else:
                 if geom.float_eq(m, 0.0):
                     y = b
                     x = self.clip_rect.xmin
                 else:
                     y = self.clip_rect.xmin * m + b
                     if m < 0:
                         y = min(clip_rect.ymax, y)
                     else:
                         y = max(clip_rect.ymin, y)
                     x = (y - b) / m
         clip_pt = geom.P(x, y)
         rays.append(geom.Line(bisector.p2, clip_pt))
     return rays
コード例 #6
0
ファイル: gcodesvg.py プロジェクト: sod4602/tcnc
 def _draw_tool_mark(self, segment, u, angle):
     # This will be the midpoint of the tool mark line.
     p = segment.point_at(u)
     if not self.gcgen.float_eq(self.tool_offset, 0.0):
         # Calculate and draw the tool offset mark.
         px = p + geom.P.from_polar(self.tool_offset, angle - math.pi)
         if self.show_toolmarks:
             self.svg.create_line(p,
                                  px,
                                  self._styles['tooloffset'],
                                  parent=self.tool_layer)
     else:
         # No tool offset
         px = p
     # Calculate the endpoints of the tool mark.
     r = self.tool_width / 2
     p1 = px + geom.P.from_polar(r, angle + math.pi / 2)
     p2 = px + geom.P.from_polar(r, angle - math.pi / 2)
     toolmark_line = geom.Line(p1, p2)
     if (not self.toolmarks
             or not toolmark_line.is_coincident(self.toolmarks[-1])):
         if self.show_toolmarks:
             self.svg.create_line(p1,
                                  p2,
                                  self._styles['toolmark'],
                                  parent=self.tool_layer)
     # Save toolmarks for toolpath outline and sub-path creation
     self.toolmarks.append(toolmark_line)
コード例 #7
0
    def _concave_vertices(self, vertices, max_angle=math.pi):
        """
        Args:
            vertices: the polygon vertices. An iterable of
                2-tuple (x, y) points.
            max_angle: Maximum interior angle of the concave vertices.
                Only concave vertices with an interior angle less
                than this will be returned.

        Returns:
            A list of triplet vertices that are pointy towards the inside
            and a new, somewhat more convex, polygon with the concave
            vertices closed.
        """
        concave_verts = []
        new_polygon = []
        clockwise = polygon.area(vertices) < 0
        i = -3 if vertices[-1] == vertices[0] else -2
        vert1 = vertices[i]
        vert2 = vertices[i + 1]
        for vert3 in vertices:
            seg = geom.Line(vert1, vert2)
            side = seg.which_side(vert3)
            angle = abs(vert2.angle2(vert1, vert3))
            if angle < max_angle and ((clockwise and side < 0) or (not clockwise and side > 0)):
                concave_verts.append((vert1, vert2, vert3))
                new_polygon.append(vert3)
            elif not new_polygon or vert2 != new_polygon[-1]:
                new_polygon.append(vert2)
            vert1 = vert2
            vert2 = vert3
        return (concave_verts, new_polygon)
コード例 #8
0
ファイル: pipelines.py プロジェクト: sod4602/tcnc
    def _linex_segment(self, ray, path1, path2):
        """ Get the segment from the starting point of the ray
        (on the first path) to its
        intersection with the second path.
        """
        ilines = []
#        d1 = self._pline_distance(ray.p1, path1)
#        logger.debug('ray d1: %.3f', d1)
        for seg in path2:
            px = ray.intersection(seg, segment=True)
            if px is not None:
#                geom.debug.draw_point(px)
                lx = geom.Line(ray.p1, px)
#                geom.debug.draw_line(lx, color='#ff00ff')
                ilines.append(lx)
        # If multiple intersections, return the shortest.
        if ilines:
#            logger.debug('intersects: %d', len(ilines))
            ilines.sort(key=lambda l: l.length())
#            ilines.sort(key=lambda lx: abs(d1 - self._pline_distance(lx.p2, path2)))
            for lx in ilines:
                if lx.length() > 0.001:
                    break
#            logger.debug('l: %f', lx.length())
#            lx = ilines[0]
#            geom.debug.draw_line(lx, color='#ff00ff', width=15, opacity=.5)
#            d = abs(d1 - self._pline_distance(lx.p2, path2))
#            logger.debug('lx d: %.3f', d)
            return lx
        return None
コード例 #9
0
ファイル: gcodesvg.py プロジェクト: sod4602/tcnc
 def plot_feed(self, endp):
     """Plot G01 - linear feed from current position to :endp:(x,y,z,a)."""
     if self.show_toolmarks:
         self._draw_tool_marks(geom.Line(self._current_xy, endp),
                               start_angle=self._current_a,
                               end_angle=endp[3])
     if self._current_xy.distance(endp) > geom.const.EPSILON:
         self.svg.create_line(self._current_xy, endp,
                              self._styles['feedline'])
     self._update_location(endp)
コード例 #10
0
ファイル: Arc.py プロジェクト: 1907931256/HeeksCAM
    def AlmostALine(self):
        mid_point = self.MidParam(0.5)
        if geom.Line(self.s,
                     self.e - self.s).Dist(mid_point) <= geom.tolerance:
            return True

        max_arc_radius = 1.0 / geom.tolerance
        radius = self.c.Dist(self.s)
        if radius > max_arc_radius:
            return True
        return False
コード例 #11
0
ファイル: gcodesvg.py プロジェクト: sod4602/tcnc
 def _fix_reversals(self, path):
     """Collapse path reversals.
     This is when the next segment direction is more than 90deg from
     current segment direction...
     """
     # This works in O(n) time...
     skip_ahead = 0
     line1 = path[0]
     fixed_path = []
     for i, line2 in enumerate(path[1:]):
         if i < skip_ahead:
             continue
         skip_ahead = 0
         angle = line1.p2.angle2(line1.p1, line2.p2)
         if abs(angle) < math.pi / 2:
             if angle > 0:
                 # right turn. corner is poking outwards.
                 #                    geom.debug.draw_point(line1.p2, color='#0000ff')
                 # Move forward until next reversal
                 for j, line2 in enumerate(path[(i + 1):]):
                     angle = line1.p2.angle2(line1.p1, line2.p2)
                     if abs(angle) > math.pi / 2:
                         #                            geom.debug.draw_line(line2, color='#ff0000')
                         line2 = geom.Line(line1.p2, line2.p2)
                         skip_ahead = i + j + 1
                         break
             else:
                 # left turn. corner is poking inwards.
                 #                    geom.debug.draw_point(line1.p2, color='#ff0000')
                 # Move forward until next reversal
                 for j, line2 in enumerate(path[(i + 1):]):
                     line1 = geom.Line(line1.p1, line2.p1)
                     angle = line1.p2.angle2(line1.p1, line2.p2)
                     if abs(angle) > math.pi / 2:
                         skip_ahead = i + j + 1
                         break
         fixed_path.append(line1)
         line1 = line2
     fixed_path.append(line1)
     return fixed_path
コード例 #12
0
ファイル: gcodesvg.py プロジェクト: sod4602/tcnc
 def _simplify_path(self, path, tolerance):
     points1, points2 = zip(*path)
     points1 = list(points1)
     points2 = list(points2)
     points1.append(points2[-1])
     points = polygon.simplify_polyline_rdp(points1, tolerance)
     new_path = []
     prev_pt = points[0]
     for next_pt in points[1:]:
         next_line = geom.Line(prev_pt, next_pt)
         new_path.append(next_line)
         prev_pt = next_pt
     return new_path
コード例 #13
0
ファイル: geomsvg.py プロジェクト: sod4602/tcnc
def convert_line(element):
    """Convert an SVG line shape element to a geom.Line.

    Args:
        element: An SVG 'line' element of the form:
           <line x1='X1' y1='Y1' x2='X2' y2='Y2/>

    Returns:
       A line segment: geom.Line((x1, y1), (x2, y2))
    """
    x1 = float(element.get('x1', 0))
    y1 = float(element.get('y1', 0))
    x2 = float(element.get('x2', 0))
    y2 = float(element.get('y2', 0))
    return geom.Line((x1, y1), (x2, y2))
コード例 #14
0
ファイル: geomsvg.py プロジェクト: sod4602/tcnc
def convert_polygon(element):
    """Convert an SVG `polygon` shape element to a list line segments.

    Args:
        element: An SVG 'polygon' element of the form:
            <polygon points='x1,y1 x2,y2 x3,y3 [...]'/>

    Returns:
       A list of geom.Line segments. The polygon will be closed.
    """
    segments = convert_polyline(element)
    # Close the polygon if not already so
    if len(segments) > 1 and segments[-1] != segments[0]:
        segments.append(geom.Line(segments[-1], segments[0]))
    return segments
コード例 #15
0
 def _convex_vertices(self, vertices):
     """
     :param vertices: the polygon vertices. An iterable of 2-tuple (x, y) points.
     :return: A list of triplet vertices that are pointy towards the outside.
     """
     pointy_verts = []
     clockwise = polygon.area(vertices) < 0
     i = -3 if vertices[-1] == vertices[0] else -2
     vert1 = vertices[i]
     vert2 = vertices[i + 1]
     for vert3 in vertices:
         seg = geom.Line(vert1, vert2)
         side = seg.which_side(vert3, inline=True)
         if side != 0 and ((clockwise and side > 0) or (not clockwise and side < 0)):
             pointy_verts.append((vert1, vert2, vert3))
         vert1 = vert2
         vert2 = vert3
     return pointy_verts
コード例 #16
0
ファイル: geomsvg.py プロジェクト: sod4602/tcnc
def convert_polyline(element):
    """Convert an SVG `polyline` shape element to a list of line segments.

    Args:
        element: An SVG 'polyline' element of the form:
            <polyline points='x1,y1 x2,y2 x3,y3 [...]'/>

    Returns:
       A list of geom.Line segments.
    """
    segments = []
    points = element.get('points', '').split()
    sx, sy = points[0].split(',')
    start_p = geom.P(float(sx), float(sy))
    prev_p = start_p
    for point in points[1:]:
        sx, sy = point.split(',')
        p = geom.P(float(sx), float(sy))
        segments.append(geom.Line(prev_p, p))
        prev_p = p
    return segments
コード例 #17
0
    def __init__(self, verts, target,
                 error):  # There are three of everything here.

        # Image coordinates for the three vertices, in pixels, listed clockwise.
        self.verts = verts

        # Target world coordinates of vertices, in meters.
        self.target = target

        # Error vector in meters (difference from the target point to be corrected.)
        self.error = error

        # Construct edge lines from each vertex to its clockwise neighbor.
        self.edges = [
            geom.Line(verts[(i + 1) % 3], verts[(i + 2) % 3]) for i in range(3)
        ]

        # Perpendicular distances from each vertex to the opposing edge line.
        self.dists = [e.signedDist(v) for v, e in zip(self.verts, self.edges)]

        pass
コード例 #18
0
ファイル: geomsvg.py プロジェクト: sod4602/tcnc
def parse_path_geom(path_data, ellipse_to_bezier=False):
    """
    Parse SVG path data and convert to geometry objects.

    Args:
        path_data: The `d` attribute value of an SVG path element.
        ellipse_to_bezier: Convert elliptical arcs to bezier curves
            if True. Default is False.

    Returns:
        A list of zero or more subpaths.
        A subpath being a list of zero or more Line, Arc, EllipticalArc,
        or CubicBezier objects.
    """
    subpath = []
    subpath_list = []
    p1 = (0.0, 0.0)
    for cmd, params in svg.parse_path(path_data):
        p2 = (params[-2], params[-1])
        if cmd == 'M':
            # Start of path or sub-path
            if subpath:
                subpath_list.append(subpath)
                subpath = []
        elif cmd == 'L':
            subpath.append(geom.Line(p1, p2))
        elif cmd == 'A':
            rx = params[0]
            ry = params[1]
            phi = params[2]
            large_arc = params[3]
            sweep_flag = params[4]
            elliptical_arc = geom.ellipse.EllipticalArc.from_endpoints(
                p1, p2, rx, ry, large_arc, sweep_flag, phi)
            if elliptical_arc is None:
                # Parameters must be degenerate...
                # Try just making a line
                logger = logging.getLogger(__name__)
                logger.debug('Degenerate arc...')
                subpath.append(geom.Line(p1, p2))
            elif geom.float_eq(rx, ry):
                # If it's a circular arc then create one using
                # the previously computed ellipse parameters.
                segment = geom.Arc(p1, p2, rx, elliptical_arc.sweep_angle,
                                   elliptical_arc.center)
                subpath.append(segment)
            elif ellipse_to_bezier:
                # Convert the elliptical arc to cubic Beziers
                subpath.extend(bezier.bezier_ellipse(elliptical_arc))
            else:
                subpath.append(elliptical_arc)
        elif cmd == 'C':
            c1 = (params[0], params[1])
            c2 = (params[2], params[3])
            subpath.append(bezier.CubicBezier(p1, c1, c2, p2))
        elif cmd == 'Q':
            c1 = (params[0], params[1])
            subpath.append(bezier.CubicBezier.from_quadratic(p1, c1, p2))
        p1 = p2
    if subpath:
        subpath_list.append(subpath)
    return subpath_list
コード例 #19
0
ファイル: pipelines.py プロジェクト: sod4602/tcnc
    def _get_segments(self, path1, path2):
        """ This is ridiculously non-optimal, but who cares...
        """
        bbox = polygon.bounding_box([p1 for p1, _p2 in path1]
                                    + [p1 for p1, _p2 in path2])
        # Make sure both paths are going more or less in the same direction
        # by checking if the distance between the starting points is less
        # than the distance between one path starting point and the other
        # path ending point.
        d1 = path1[0].p1.distance(path2[0].p1)
        d2 = path1[0].p1.distance(path2[-1].p2)
        if d1 > d2:
            geom.util.reverse_path(path2)
        rays = [geom.Line(path1[0].p1, path2[0].p1)]
        rayside = path1[0].which_side(path2[0].p1)
        p0 = path1[0].p1
        for p1, p2 in path1[1:]:
            if abs(p1.angle2(p0, p2)) > geom.const.EPSILON:
                # The angle bisector at each vertex
                bisector = geom.Line(p1, p1.bisector(p0, p2))
                # Make sure it's pointing the right way
                if geom.Line(p0, p1).which_side(bisector.p2) != rayside:
                    bisector = bisector.flipped()
#                geom.debug.draw_line(bisector, width=11)
                bisector = bisector.extend(bbox.diagonal())
                # See if it intersects a segment on the other path
                lx = self._linex_segment(bisector, path1, path2)
                if lx is not None:
                    rays.append(lx)
            p0 = p1
        # Do the same for the other path
        rayside = -rayside
        p0 = path2[0].p1
        for p1, p2 in path2[1:]:
            bisector = geom.Line(p1, p1.bisector(p0, p2))
            if geom.Line(p0, p1).which_side(bisector.p2) != rayside:
                bisector = bisector.flipped()
#            geom.debug.draw_line(bisector, width=11)
            bisector = bisector.extend(bbox.diagonal())
            lx = self._linex_segment(bisector, path2, path1)
            if lx is not None:
                rays.append(lx.reversed())
            p0 = p1
        # Last line joining the path endpoints
        rays.append(geom.Line(path1[-1].p2, path2[-1].p2))
        # Sort the segment endpoints on each path by distance from first
        # path endpoint. Then connect the sorted segment endpoints.
        p1list = [seg.p1 for seg in rays]
        p2list = [seg.p2 for seg in rays]
        p1list.sort(key=lambda p: self._pline_distance(p, path1))
        p2list.sort(key=lambda p: self._pline_distance(p, path2))
        rays = [geom.Line(p1, p2) for p1, p2 in zip(p1list, p2list)]
        # Sort the segments by distance on first path
#        rays.sort(key=lambda seg: self._pline_distance(seg.p1, path1))
#        for i, ray in enumerate(rays):
#            logger.debug('ray[%d]: %.3f, %.3f', i, ray.length(), self._pline_distance(ray.p1, path1))
#            geom.debug.draw_point(ray.p1, radius=7, color='#ffff00')
#        geom.debug.draw_point(rays[8].p1, radius=7, color='#ffff00')
#        geom.debug.draw_line(path1[5], color='#ffff00', width=7)
#        if path1[5].point_on_line(rays[8].p1):
#            logger.debug('yep')
#        logger.debug('d: %.3f', self._pline_distance(rays[25].p1, path1))
#        return self._elim_crossings(rays, path1, path2)
        return rays
コード例 #20
0
ファイル: Grid.py プロジェクト: 1907931256/HeeksCAM
def RenderGrid2(cad, view_point, max_number_across, in_between_spaces,
                miss_main_lines, bg, cc, brightness, plane_mode):
    zval = 0.5
    size = view_point.viewport.GetViewportSize()
    sp = []
    sp.append(geom.Point3D(0, 0, zval))
    sp.append(geom.Point3D(size.GetWidth(), 0, zval))
    sp.append(geom.Point3D(size.GetWidth(), size.GetHeight(), zval))
    sp.append(geom.Point3D(0, size.GetHeight(), zval))

    vx, vy, plane_mode2 = view_point.GetTwoAxes(False, plane_mode)
    datum = geom.Point3D(0, 0, 0)
    orimat = cad.GetDrawMatrix(False)
    datum.Transform(orimat)
    orimat = geom.Matrix(datum, vx, vy)
    unit_forward = view_point.forwards_vector().Normalized()
    plane_dp = math.fabs(
        geom.Point3D(0, 0, 1).Transformed(orimat) * unit_forward)
    if plane_dp < 0.3: return
    plane = geom.Plane(
        geom.Point3D(0, 0, 0).Transformed(orimat),
        geom.Point3D(0, 0, 1).Transformed(orimat))

    for i in range(0, 4):
        p1 = view_point.glUnproject(sp[i])
        sp[i].z = 0.0
        p2 = view_point.glUnproject(sp[i])
        if p1.Dist(p2) < 0.00000000001: return

        line = geom.Line(p1, p2)

        pnt = line.IntersectPlane(plane)
        if pnt != None:
            sp[i].x = (pnt * vx) - (datum * vx)
            sp[i].y = (pnt * vy) - (datum * vy)
            sp[i].z = 0.0

    b = geom.Box3D()
    for i in range(0, 4):
        b.InsertPoint(sp[i].x, sp[i].y, sp[i].z)

    width = b.Width()
    height = b.Height()
    biggest_dimension = None
    if height > width: biggest_dimension = height
    else: biggest_dimension = width
    widest_spacing = biggest_dimension / max_number_across
    dimmer = False
    dimness_ratio = 1.0
    spacing = None

    if cad.draw_to_grid:
        spacing = cad.digitizing_grid
        if miss_main_lines == False: spacing = spacing * 10
        if spacing < 0.0000000001: return
        if biggest_dimension / spacing > max_number_across * 1.5: return
        if biggest_dimension / spacing > max_number_across:
            dimmer = True
            dimness_ratio = (max_number_across * 1.5 - biggest_dimension /
                             spacing) / (max_number_across * 0.5)
    else:
        l = math.log10(widest_spacing / cad.view_units)
        intl = int(l)
        if l > 0: intl = intl + 1
        spacing = math.pow(10.0, intl) * cad.view_units

    if cad.grid_mode == 3:
        dimmer = True
        dimness_ratio = dimness_ratio * plane_dp
        dimness_ratio = dimness_ratio * plane_dp

    ext2d = [b.x[0], b.x[1], b.x[3], b.x[4]]

    for i in range(0, 4):
        intval = int(ext2d[i] / spacing)

        if i < 2:
            if ext2d[i] < 0: intval -= 1
            elif ext2d[i] > 0: intval += 1
            ext2d[i] = intval * spacing
    if cc:
        col = HeeksColor(cc.red, cc.green, cc.blue)
        if cad.grid_mode == 3:
            if plane_mode2 == 0:
                col.green = int(0.6 * float(bg.green))
            elif plane_mode2 == 1:
                col.red = int(0.9 * float(bg.red))
            else:
                col.blue = bg.blue

        if dimmer:
            d_brightness = float(brightness) * dimness_ratio
            uc_brightness = int(d_brightness)
            glColor4ub(col.red, col.green, col.blue, uc_brightness)
        else:
            glColor4ub(col.red, col.green, col.blue, brightness)

    glBegin(GL_LINES)
    extra = 0.0
    if in_between_spaces: extra = spacing * 0.5

    x = ext2d[0] - extra
    while x < ext2d[2] + extra:
        if miss_main_lines:
            xr = x / spacing / 5
            temp = xr
            if temp > 0: temp += 0.5
            else: temp -= 0.5
            temp = int(temp)
            temp = float(temp)
            if math.fabs(xr - temp) < 0.1:
                x += spacing
                continue
        temp = datum + (vx * x) + (vy * ext2d[1])
        glVertex3d(temp.x, temp.y, temp.z)
        temp = datum + (vx * x) + (vy * ext2d[3])
        glVertex3d(temp.x, temp.y, temp.z)
        x += spacing

    y = ext2d[1] - extra
    while y < ext2d[3] + extra:
        if miss_main_lines:
            yr = y / spacing / 5
            temp = yr
            if temp > 0: temp += 0.5
            else: temp -= 0.5
            temp = int(temp)
            temp = float(temp)
            if math.fabs(yr - temp) < 0.1:
                y += spacing
                continue
        temp = datum + (vx * ext2d[0]) + (vy * y)
        glVertex3d(temp.x, temp.y, temp.z)
        temp = datum + (vx * ext2d[2]) + (vy * y)
        glVertex3d(temp.x, temp.y, temp.z)
        y += spacing

    glEnd()
コード例 #21
0
ファイル: offset.py プロジェクト: sod4602/tcnc
def offset_path(path, offset, min_arc_dist, g1_tolerance=None):
    """Recalculate path to compensate for a trailing tangential offset.
    This will shift all of the segments by `offset` amount. Arcs will
    be recalculated to correct for the shift offset.

    Args:
        path: The path to recalculate.
        offset: The amount of tangential tool trail.
        min_arc_dist: The minimum distance between two connected
            segment end points that can be bridged with an arc.
            A line will be used if the distance is less than this.
        g1_tolerance: The angle tolerance to determine if two segments
            are g1 continuous.

    Returns:
        A new path

    Raises:
        :class:`cam.toolpath.ToolpathException`: if the path contains segment
            types other than Line or Arc.
    """
    if geom.float_eq(offset, 0.0):
        return path
    offset_path = []
    prev_seg = None
    prev_offset_seg = None
    for seg in path:
        if seg.p1 == seg.p2:
            # Skip zero length segments
            continue
        if isinstance(seg, geom.Line):
            # Line segments are easy - just shift them forward by offset
            offset_seg = seg.shift(offset)
        elif isinstance(seg, geom.Arc):
            offset_seg = offset_arc(seg, offset)
        else:
            raise toolpath.ToolpathException('Unrecognized path segment type.')
        # Fix discontinuities caused by offsetting non-G1 segments
        if prev_seg is not None:
            if prev_offset_seg.p2 != offset_seg.p1:
                seg_distance = prev_offset_seg.p2.distance(offset_seg.p1)
                # If the distance between the two segments is less than the
                # minimum arc distance or if the segments are G1 continuous
                # then just insert a connecting line.
                if (seg_distance < min_arc_dist or geom.segments_are_g1(
                        prev_offset_seg, offset_seg, g1_tolerance)):
                    connect_seg = geom.Line(prev_offset_seg.p2, offset_seg.p1)
                else:
                    # Insert an arc in tool path to rotate the tool to the next
                    # starting tangent when the segments are not G1 continuous.
                    # TODO: avoid creating tiny segments by extending
                    # offset segment.
                    p1 = prev_offset_seg.p2
                    p2 = offset_seg.p1
                    angle = prev_seg.p2.angle2(p1, p2)
                    # TODO: This should be a straight line if the arc is tiny
                    connect_seg = geom.Arc(p1, p2, offset, angle, prev_seg.p2)


#                    if connect_seg.length() < 0.01:
#                        logger.debug('tiny arc! length= %f, radius=%f, angle=%f', connect_seg.length(), connect_seg.radius, connect_seg.angle)
                connect_seg.inline_start_angle = prev_seg.end_tangent_angle()
                connect_seg.inline_end_angle = seg.start_tangent_angle()
                offset_path.append(connect_seg)
                prev_offset_seg = connect_seg
            elif (geom.segments_are_g1(prev_seg, seg, g1_tolerance)
                  and not hasattr(prev_seg, 'ignore_g1')
                  and not hasattr(seg, 'ignore_g1')):
                # Add hint for smoothing pass
                prev_offset_seg.g1 = True
        prev_seg = seg
        prev_offset_seg = offset_seg
        offset_path.append(offset_seg)
    # Compensate for starting angle
    start_angle = (offset_path[0].p1 - path[0].p1).angle()
    offset_path[0].inline_start_angle = start_angle
    return offset_path