how to convert path to box/polygon?

edited August 2014 in Layout
"Edit/Selection/Merge Shapes" does not work. Sometime the path will just disappear. In most case, they are converted but does not get filled. How can I convert a path to filled polygon or box?

Another question will be how to convert polygon to path?

Comments

  • edited August 2014

    Hi,

    once again ... sorry for the late reply.

    A path will disappear on merging if it has not width. That is because the merge operation creates an equivalent polygon area and if the path does not cover an area none is generated.

    Please consider the following: in GDS files, the objects typically represent some "material". There are no "lines" in GDS (well, it's possible, but not common). There is only "area" and all operations will perform some transformation of "area" into "area". Plain lines (such as zero-width paths) do not represent area and get lost in these operations.

    Maybe that also explains why there is no polygon to path conversion. I guess you are looking for an operation that traces the border of a polygon. But again - lines are not popular objects in GDS.

    Matthias

  • edited November 2014
    In case you consider a path to be a line (width=0), how about:
    (1. Create path)
    2. Open path properties (double click)
    3. Select & copy all coordinates/points from the list --> [CTRL]+[A] --> [CTRL]+[C]
    (4. delete path)
    5. create temporary polygon (e.g. triangle)
    6. Open polygon properties (double click)
    7. Replace the coordinates by pasting from clipboard --> [CTRL]+[A] --> [CTRL]+[V]
    8. Done :-)

    - In case of closed paths (start point = end point) you should delete the duplicate point.
    - Polygon to path works the same way (note: copy 1st point to the end of the list to get a closed path again).
    - I have no idea how to convert the actual >>area<< covered by path/box to a polygon.
  • edited November -1

    Hi,

    one way to solve the problem, thanks :-)

    To convert a path or box to a polygon, you can use "Edit/Selection/Merge Shapes". The main functionality of that function is to join overlapping shapes into one polygon. But a side effect is that everything selected will be converted to polygons, also if the selection is a single, non-polygon shape.

    Matthias

  • ksks
    edited November -1
    Hi,

    Using the merge function seem to delete/remove the object as well. The ability to convert zero width paths to polygons would be a great feature.
    Any ideas?

    Thx much

    K-
  • ksks
    edited November -1
    Hi,
    A similar effect can be obtained by selecting "merge lines and auto-close open contours," in the dxf reader options panel.

    Is there a way to manually preform the same operation in the layout editor with selected objects?

    Thx
    K-
  • edited November 2014

    No, there is no such feature. And I don't know anybody who needs it, apart from the DXF users. And for them there is the reader option.

    Give me a thousand "likes" and I'll be motivated enough to implement it ...

    Matthias

  • ksks
    edited November -1
    Thank you for the reply.

    I've tried to create a simple macro to accomplish the task. I can convert the object to a poly but the macro seems to double up the coords. Maybe you could point me in the right direction

    view.transaction("Convert to Poly")
    begin


    view.each_object_selected do |obj|

    if obj.shape.is_path?
    poly = obj.shape
    obj.shape.clear
    obj.shape.polygon = poly

    end
    end
    end
    ensure
    view.commit
    view.cancel
    end

    Thanks
  • ksks
    edited November -1
    BTW, A thousand "likes" is not out of the question.

    K-
  • edited April 2016

    Hi ks,

    the path to polygon conversion using the points is just half the truth. Emulating what the DXF reader does is far more complex - the issues are hole resolution, orientation normalization and such.

    Here is a script which basically does what the DXF reader implements. The core is the EdgeProcessor which can convert edge sets back to polygons doing all the magic of hole insertion and so forth. Decomposition of the paths into edges is easy but the EdgeProcessor is picky, so we'll have to sort out the edges which do not form oriented loops. The core functionality used within the DXF reader is not directly available to Ruby yet, so I am providing a brute force implementation here. It does a piecewise elimination of dangling edges and corrects the edge direction n a second step if required. Please see the notes in the text:

    shapes = []
    
    cell = nil
    layer = nil
    
    # collect the zero-width paths
    lv = RBA::LayoutView::current
    
    begin
    
      lv.transaction("Join lines")
    
      lv.each_object_selected do |s|
        if !s.is_cell_inst? && s.shape.is_path? && s.shape.path_width == 0
          shapes << s.shape
          layer ||= s.layer
          cell ||= lv.cellview(s.cv_index).layout.cell(s.cell_index)
        end
      end
    
      lv.cancel
    
      # collect the edges
      edges = []
      shapes.each do |s|
        p0 = nil
        s.path.each_point do |p|
          p0 && p0 != p && (edges << RBA::Edge::new(p0, p))
          p0 = p
        end
      end
    
      # By providing a hash and eql? function we can use 
      # points as keys in hashes
      class RBA::Point
        def eql?(b)
          self == b
        end
        def hash
          s1 = 1
          s2 = 0
          [ self.x, self.y ].each do |v|
            s1 = (s1 + v) % 65521
            s2 = (s2 + s1) % 65521
          end
          (s2 << 16) | s1
        end
      end
    
      # count the number of times a point is present
      point_weight = {}
      edges.each do |e|
        point_weight[e.p1] = (point_weight[e.p1] || 0) + 1
        point_weight[e.p2] = (point_weight[e.p2] || 0) + 1
      end
    
      # sort out edges with a dangling endpoint
      # NOTE: this algorithm is O(N**2) in the worst case
      # and is INEFFICIENT. 
      try_again = true
      while try_again
    
        try_again = false
    
        new_edges = []
        edges.each do |e|
          pw1 = point_weight[e.p1]
          pw2 = point_weight[e.p2]
          if pw1 == 1 || pw2 == 1
            point_weight[e.p1] -= 1
            point_weight[e.p2] -= 1
            try_again = true
          else
            new_edges << e
          end
        end
    
        edges = new_edges
    
      end
    
      # count the number of times a point is present once again,
      # this time assigning +1 for a start point and -1 for an
      # end point. Hence a weight of 0 means there are edges 
      # connected in the right way (start to end point).
      point_weight = {}
      edges.each do |e|
        point_weight[e.p1] = (point_weight[e.p1] || 0) + 1
        point_weight[e.p2] = (point_weight[e.p2] || 0) - 1
      end
    
      # Change edge orientation in to correct 
      # wrongly oriented edges
      try_again = true
      while try_again
    
        try_again = false
    
        edges.each do |e|
          pw1 = point_weight[e.p1]
          pw2 = point_weight[e.p2]
          if pw1 > 0 || pw2 < 0
            point_weight[e.p1] -= 2
            point_weight[e.p2] += 2
            e.swap_points
            try_again = true
          end
        end
    
      end
    
      # here is the actual edge to polygon conversion!
      polygons = RBA::EdgeProcessor::new.simple_merge_e2p(edges, true, false)
    
      # delete the edges and insert the polygons 
      # CAUTION: the polygons are put on the layer and cell where the first path was 
      # so don't select paths from multiple layers and cells
      shapes.each do |s|
        s.delete
      end
      if cell 
        polygons.each do |p|
          cell.shapes(layer).insert(p)
        end
      end
    
    ensure
      lv.commit
    end
    

    Worth a thousand likes, isn't it :-)

    Matthias

  • ksks
    edited November -1
    Absolutely!! - Thank you very much for your help Matthias
Sign In or Register to comment.