# How to find a circle vertices without creating it?

Hi,
I needed circle vertices and used the following code.

``````              cir = Sketchup.active_model.entities.add_circle cp, v1, (rad)
cir.each { |cp| pts << cp.vertices.position.to_a }
cir.each { |cp| cp.erase! }
``````

My problem is I use code in onLButtonDown and the circle appears in Undo. Is there any way I got circle vertices without drawing it?
Your help will be highly appreciated.

Hi,

If I was you, I would probably calculate them using sin and cosin.
For example if you want 8 points around a defined point:

``````def circle_points(pt)
out_points=[]
angle=0
8.times{
out_points<<Geom::3dPoint.new(px,py,pt)
angle+=45
}
end

point=Geom::3dPoint.new(10,20,30)
round_points=circle_points(point)

``````

Of course change the interval and number of times if you need more samples.
Best regards

direct calculating can be difficult. I calculate circle points in x y sheet and origin then move and rotate points. It works well.

``````              teta = 2 * Math::PI / 16
for i in 0...17
x1 = rad * Math::cos(i * teta)
y1 = rad * Math::sin(i * teta)
pts << [x1, y1, 0]
end
angle = vec.angle_between [0, 0, 1]
vec2 = vec * [0, 0, 1]
vec2 = [1, 0, 0] if vec2.length < 0.001
tr = Geom::Transformation.new cp
tr_rt = Geom::Transformation.rotation [0, 0, 0], vec2, -angle
pts[@st].each{ |p| p = p.transform! tr * tr_rt }
``````

FYI: You don’t need to use a block iterator to get an array of points.
You can get the virtual curve object from the first edge, then get the array
of it’s vertices and map them to position points:

``````pts = cir_edges.first.curve.vertices.map(&:position)
``````

Whenever you need to erase multiple elements, do not use `#erase!` within an iterator block.
Instead use the bulk erase method:

``entities.erase_entities(cir_edges)``
1 Like

The title indicates you don’t want to create a circle. We can usually make use of the Sketchup API to avoid having to use sin() and cos():

``````  number_of_edge_curves = 16
theta = 2.0 * Math::PI / number_of_edge_curves
rot_tr = Geom::Transformation.rotation( ORIGIN, Z_AXIS, theta )
point = Geom::Point3d.new( 1.0, 0.0, 0.0 ) # pts with radius of unity
pts = Array.new
number_of_edge_curves.times do
pts << point.clone
point.transform!( rot_tr )
end
...
translate = Geom::Transformation.new cp
tr_rt = Geom::Transformation.rotation ORIGIN, vec2, -angle
scaling = Geom::Transformation.scaling( ORIGIN, scale_factor )
pts.map!{|point| point.transform( translate * tr_rt * scaling) }
``````

Note: Although you have 16 segments for the circle, the default is 24.

The last time through the loop results in a final point being calculated that is never used. It should rotate the point at or near the initial starting point, which is already in the first array element. Instead of setting the points based on a radius, I set it to unity, and the radius can be used as a scale factor.

Notice use of the “map!” method instead of “each”.

1 Like

May I ask the reason? Don’t you think at end of the day SU will use SIN and COS for rotation?

I use points in view.draw_polyline and the last point should be the same as the first point to have a complete circle. I saved the code.

1 Like

For myself, SIN and COS are more error prone. You said:

``````pts << pts.first.clone