Create a plugin to round corners

Hello, I’m developing a plugin and I need a way to round corners. I know there’s a round corner plugin that already does this, I wanted to include it in a simpler way without the user having to purchase round corner, which is very robust and goes beyond what I need. I would appreciate it if someone could guide me in a ruby ​​logic to implement for rounding corners.

You need to be a little more specific about what you want, but don’t expect someone to do it for you. Usually, we can help you here if you are posting some code that you’ve written.
You should also talk about your familiarity with Ruby and the Sketchup Ruby API.

This is an “infinitely” simplified quick code concept (It performs no checks, it just assumes a certain situation…), so that only works in special cases, like this.

round_c

def round_corner( radius = 5.mm )
  model = Sketchup.active_model
  entities = model.active_entities
  selection = model.selection
  edge = selection.first
  face1, face2 = edge.faces
  f1_vec = face1.normal.reverse
  f2_vec = face2.normal.reverse
  angle = f1_vec.angle_between(f2_vec)
  pt0 = edge.start.position
  pt1 = pt0.offset(f1_vec, radius)
  pt2 = pt0.offset(f2_vec, radius)
  line1 = [ pt1, f2_vec ]
  line2 = [ pt2, f1_vec ]
  center = Geom.intersect_line_line(line1, line2)
  xaxis = face1.normal
  model.start_operation("Round Corner", true)
  arc_edges = entities.add_arc(center, xaxis, edge.line[1], radius, 0, angle)
  arc_pts = arc_edges.first.curve.vertices.map(&:position)
  face_round = entities.add_face(arc_pts<<pt0)
  face_round.followme(edge)
  model.commit_operation
end
round_corner

I don’t have any code written yet because I’m still very new to Ruby. The code I’ve tried to write doesn’t even come close to what I need. That’s why I haven’t uploaded any code yet.

Vídeo sem título

What I need is something like rounding a corner on a 2D plane, like I show in the video. Rounding the corners and being able to adjust the angle and radius of the rounding, either inward or outward.

Explore the native arc tools.

1 Like

Well, eider you gave us a wrong video, or you have other meaning of round corner, I do not see any of corner rounded on your animation. What I see you draw a circle using one of the side edge of a rectangle as diameter and deleted the half of the circle as well as the face.

The roundcorner extension mentioned in your first post has nothing to do with this. (Unless, again, you’re talking about something else.)

I concluded that you are not familiar with the Ruby API, but also with Sketchup itself. Like @DanRathbun suggested, explore the usage of SketchUp native tools first, then, when you know it well, you can start to think about programming.

__
You do not need to quote my code right after my post, especially if you are not using or not altered it…

Edit:
Perhaps this is what you need ?!?
https://extensions.sketchup.com/extension/4b1cbca1-5af7-41db-baa0-eb1f6b69ae40/radius-tool

Those error messages are because variable names in Ruby start with lower case letters. Starting with a capital letter indicates a constant. This is Ruby 101.

Sorry to quote your code, I’m still new to the forum and I don’t know how the rules work here. I want to clarify that my goal is not just to round corners, but to work with sides. For example, if I have a straight line and I want to keep the two endpoints intact, but insert intermediate segments that curve the line - so that, if I select two edges in a 2D plane, the script rounds the common vertex, and if I select only one edge, it is curved (where a negative radius value curves ‘inwards’ and a positive value ‘outwards’).

Below is an example of a script that tries to integrate both functionalities:


def round_corner(radius = 5.mm, segments = 12)
  model = Sketchup.active_model
  entities = model.active_entities
  selection = model.selection

  if selection.empty?
    UI.messagebox("Selecione uma ou duas arestas (em plano 2D).")
    return
  end

  # Caso 1: Duas arestas selecionadas – arredondar o vértice comum
  if selection.size == 2 && selection.all? { |e| e.is_a?(Sketchup::Edge) }
    edge1, edge2 = selection.to_a

    # Procura o vértice comum entre as arestas
    common_point = [edge1.start.position, edge1.end.position].find do |pt|
      [edge2.start.position, edge2.end.position].include?(pt)
    end

    unless common_point
      UI.messagebox("As arestas selecionadas não compartilham um vértice comum.")
      return
    end

    # Determina os pontos opostos ao vértice comum
    pt1 = (edge1.start.position == common_point) ? edge1.end.position : edge1.start.position
    pt2 = (edge2.start.position == common_point) ? edge2.end.position : edge2.start.position

    vec1 = (pt1 - common_point).normalize
    vec2 = (pt2 - common_point).normalize

    angle = vec1.angle_between(vec2)
    if angle == 0 || angle >= Math::PI
      UI.messagebox("Ângulo inválido para arredondamento.")
      return
    end

    # Calcula o deslocamento ao longo de cada aresta
    offset = radius / Math.tan(angle / 2.0)
    new_pt1 = common_point.offset(vec1, offset)
    new_pt2 = common_point.offset(vec2, offset)

    # Calcula o centro do arco utilizando a bissetriz
    bisector = (vec1 + vec2).normalize
    d = radius / Math.sin(angle / 2.0)
    arc_center = common_point.offset(bisector, d)

    start_vector = (new_pt1 - arc_center).normalize

    arc_edges = entities.add_arc(arc_center, start_vector, vec1.cross(vec2).normalize, radius.abs, 0, angle, segments)
    if arc_edges.empty?
      UI.messagebox("Não foi possível criar o arco para arredondar o vértice.")
      return
    end

    UI.messagebox("Arredondamento do vértice concluído!")
    return

  # Caso 2: Apenas uma aresta selecionada – encurvar a reta mantendo os pontos finais
  elsif selection.size == 1 && selection.first.is_a?(Sketchup::Edge)
    edge = selection.first
    a = edge.start.position
    b = edge.end.position
    l = a.distance(b)
    
    if l == 0
      UI.messagebox("A aresta possui comprimento zero.")
      return
    end
    if (l / 2.0) > radius.abs
      UI.messagebox("Valor de raio insuficiente para curvar a aresta.")
      return
    end

    d = (b - a).normalize
    # Define o vetor perpendicular no plano; usa-se Z_AXIS para um plano 2D (XY)
    perp = Z_AXIS.cross(d).normalize
    # Se o valor do raio for negativo, inverte o sentido da curva
    perp = (radius < 0) ? -perp : perp

    m = Geom.linear_combination(0.5, a, 0.5, b)
    h = Math.sqrt(radius.abs**2 - (l / 2.0)**2)
    arc_center = m.offset(perp, h)

    start_vector = (a - arc_center).normalize
    arc_angle = (a - arc_center).angle_between(b - arc_center)

    arc_edges = entities.add_arc(arc_center, start_vector, Z_AXIS, radius.abs, 0, arc_angle, segments)
    if arc_edges.empty?
      UI.messagebox("Não foi possível criar a curva na aresta.")
      return
    end

    # Remove a aresta original, se desejar que apenas a curva permaneça
    edge.erase!
    UI.messagebox("Curvatura da aresta concluída!")
    return

  else
    UI.messagebox("Selecione uma ou duas arestas (em plano 2D).")
    return
  end
end

round_corner