Variable Space Between lines

Hi,

I have a Question but I dont know If Its possible with Ruby.

What Im Looking for is a way to Draw multiple lines with different space between them. For example i want to Draw 4 lines. Space between the first two lines is 200cm the third line a space of 100cm and the last line a space from 300cm. Is there a simple way to do that.? Is saw something like this in video

Thanks

The only part from this video i’m Looking for is the method sees use in the input box

3@3m, 4m, 5m is this a normal way to collect data in one line of text?

Maybe someone knows that

Thanks

That could be described as CSV data (Comma Separated Values,) as yes it is a very old way of separating data.

BUT, it has a drawback, especially in SketchUp inputboxes. Euro users often use the comma as a decimal separator, so for them they’ll use the semi-colon as a value separator.

So, you’ll need to determine what the value (list) separator is, and what the decimal separator is. The API added a submodule for this in SketchUp v2016M1:

if defined?(Sketchup::RegionalSettings)
  LIST_SEPARATOR = Sketchup::RegionalSettings::list_separator
else
  begin
    "3,3mm".to_l
  rescue
    # comma not used for decimal separator:
    LIST_SEPARATOR = ','
  else
    # No error, so comma is used for decimal separator:
    LIST_SEPARATOR = ';'
  end
end

Then, use standard String class methods to split the string and strip the results.

input = "3@3m, 4m, 5m"
# or: input = "3@3m; 4m; 5m"

spacings = []
values = input.split(LIST_SEPARATOR)
values.each {|v|
  if v.include?('@')
    i = v.split('@')
    num = i.first.strip.to_i
    interval = i.last.strip.to_l
    num.times do
      spacings << interval
    end
  else
    spacings << v.strip.to_l
  end
}

Then, with the spacings do a loop creating or copying the geometry:

model.start_operation("Spaced Geometry")
  spacings.each {|interval|
    # Call a method that uses the interval:
    make_geometry(interval)
  }
model.commit_operation

P.S. - I have no idea in which axis the interval will do it’s work (nor what the start point is,) … this is up to you.

2 Likes

Thanks,

This is exactly what i was looking for.

Last question, i added a method of an example cline. But it doens’t do the interval. num.times is doing it’s job but the space between them is not working. i added a messagbox under this part interval = i.last.strip.to_l and that gives the right value. So ther must be something with the make_geometry(interval) i think?

def make_geometry( constline  )

point1 = Geom::Point3d.new(0,0,0)
point2 = Geom::Point3d.new(0,2000.mm,0)
constline = @ent.add_cline(point1, point2)
end

model.start_operation("Spaced Geometry")
  spacings.each {|interval|
    # Call a method that uses the interval:
    make_geometry(interval)    
  }

model.commit_operation

You are passing the current interval to your make_geometry method in the spacings.each loop, but the make_geometry does nothing with the interval you passed, it just uses hard-wired values for point1 and point2. And the last line setting constline = @ent.add_cline is pointless, as the variable it assigns is temporary (the argument) and the method returns the last value anyway, whether assigned to something or not.
You should do something with the argument in make_geometry, such as add it to one of the coordinates of the points you create.

1 Like

So the question is how to get the values from the input to the def method so you can use it to create clines between it?

Your snippet is passing each value of interval to make_geometry in the each block. It arrives in make_geometry(constline) as the value of ‘constline’. So you just need to do something with constline in the body of the method.

This is fundamental Ruby. Maybe you need to study up some more on the basics?

1 Like

Thanks for the answer.

I tried a lot of different things with this code to get the lines on the given places also add some puts.

But i can’t find what is going wrong because the interval given the right sizes in mm.

Also tried some things with pointx.offset!([1,0,0],(spacings)) but also this type of code doens’t transform it right.

Could someone help with this part?

Thanks

How about trying something like:

def make_geometry( constline  )

point1 = Geom::Point3d.new(constline,0,0)
point2 = Geom::Point3d.new(constline,2000.mm,0)
@ent.add_cline(point1, point2)
end

Why did you think the argument passed to make_geometry would have any effect when your code doesn’t do anything with it (other than pointlessly assign the return from add_cline to it)? As I wrote earlier, you seem confused about basic concepts of Ruby methods.

1 Like

The offset must use the interval passed as the argument.

Let us say that the object will be copied along the x axis, and that you have already gotten 2 points from the user (@point1, @point2 ) via an Sketchup::InputPoint instance in your Rubytool *

See example a few posts below …


* Also see the example “linetool.rb” in the Example Ruby Scripts extension.


At some time, you’ll need to learn how to do these simple things by yourself.

Have you read any of the free Ruby books listed in my Ruby Learning Resources listing ?

1 Like

Thanks again for the help and it is working :slight_smile:

I know i must learn a lot in Ruby and sometimes is language my biggest problem what makes it harder to understand sometimes.

Going to read the stuff you sent

I actually did not show doing this in the last example, so here is better example that passes the interval and creates the vector object locally inside the make_geometry() method:

def make_geometry( interval )
  # Create a vector for offsetting points along the x axis:
  vec = Geom::Vector3d::new(interval,0,0)
  @point1.offset!(vec)
  @point2.offset!(vec)
  @ents.add_cline( @point1, @point2 )
end

model.start_operation("Spaced Geometry")
  spacings.each {|interval|
    # Call a method that uses the interval:
    make_geometry(interval)
  }
model.commit_operation

Hi,

I have this code now working also with dimension lines.

I use the code to create the dimension lines:

     @offset2=[0, -50, 0]`

```def make_geometry3 ( interval )
      @intermediate=@start2.offset([1,0,0], interval)
      @ent.add_dimension_linear(@start2, @intermediate, @offset2)
      @start2=@intermediate
      @intermediate=@start.offset(@vec, interval)```

<img src="//cdck-file-uploads-global.s3.dualstack.us-west-2.amazonaws.com/sketchup/original/3X/6/5/658fd9ea38ad9f7c30237971b5749faec8441b54.jpg" width="690" height="311">

I was trying to do the same thing to create a component or group that uses the variable length but without success.
Can you use the spacings values to create components or groups this way?

Thanks

Yes.


P.S. - When you post code, please put it between lines of triple backticks (with the coding language name on the first line if you know it.)

Like this:

```ruby
# code goes here
```

Hi,

Strange i used the trippel backticks.

But it is possible you say. Do i have to search it in a push pull code, transformation.scaling or set dynamic attributes? I tried all three without the success for now.

Thanks

if you add the word ‘ruby’ as Dan shows you’ll get the appropriate syntax highlighting…

john

I do not know what “this way” is because your example code is incomplete, poorly spaced, and not correctly indented.

I will guess.

If you mean, you wish to create one component, and then insert instances of this component at the spacings, then yes you can do this.

Examples (untested) just for ideas:

def make_component(cname = "New Component Name")
  model = Sketchup.active_model
  comp  = model.definitions.add(cname)
  cents = comp.entities
  # Add geometry to cents here
  return comp
end

def make_geometry( comp, trans )
  aents = Sketchup.active_model.active_entities
  aents.add_instance( comp, trans )
end
def do_operation( 
  start_point = Geom::Point3d::new( 0, 0, 0 ),
  op_name = "Spaced Components" 
)
  model.start_operation( op_name )
    # Make the component definition:
    comp = make_component("Test Component")
    # Create a transformation set to the start point:
    trans = Geom::Transformation.new( start_point )
    # Make the first component instance:
    make_geometry( comp, trans )
    # Make the spaced component instances:
    @spacings.each {|interval|
      # Create a x-axis vector for this interval:
      vec = Geom::Vector3d::new( interval, 0, 0 )
      # Apply this interval vector to the running transform:
      trans = trans * Geom::Transformation::new( vec )
      # Call a method that uses the transformation:
      make_geometry( comp, trans )
    }
  model.commit_operation
end

Thanks Dan,

That is what i was searching for :slight_smile: with some little changes it works great. I also added the part that makes the length of the component equal to the variable spacings.
So thanks Dan :slight_smile:

def make_component(cname = "New Component Name")
  model = Sketchup.active_model
  cdef  = model.definitions.add(cname)
  cents = cdef.entities 
  # Add geometry to cents here
    fac = cents.add_face([0,0,0],[0,100.mm,0],[0,100.mm,300.mm],[0,0,300.mm])
    fac.reverse!
    fac.pushpull(100.mm)
  return cdef
end

def make_geometry( cdef, trans )
  aents = Sketchup.active_model.active_entities
  aents.add_instance( cdef, trans )
end

@start_point = Geom::Point3d::new( 0, 0, 0)

@model.start_operation( "C-profiel" )
    # Make the component definition:
    comp_def = make_component("C-profiel")
    # Create a transformation set to the start point:
    trans = Geom::Transformation.new( @start_point )     
      spacings.each {|interval|
      # Create a x-axis vector for this interval:
      vec = Geom::Vector3d::new( interval, 0, 0 )
      # Apply this interval vector to the running transform:
      trans = trans * Geom::Transformation::new( vec )
      # Call a method that uses the transformation:
      t = Geom::Transformation.scaling @start_point, interval/3.937, 1 , 1 
      make_geometry( comp_def, trans*t )
    }
  @model.commit_operation

Hi,

I have a question about this part:

 t = Geom::Transformation.scaling @start_point, interval/3.937, 1 , 1 
 make_geometry( comp_def, trans*t )

first i made a component in the code. But i now want to use one from my c: drive.
but i can’t get the dc updated so the length is correct. See my picture below, i have made an interval from 4000 mm but the dc length is still 100 mm in the component options.

Normaly you can solve this with

dcs = $dc_observers.get_latest_class
dcs.redraw_with_undo(cdef)

But this isn’t working?

You would have to insert the instance, then set the “LenX” attribute in the instance’s “dynamic_attributes” dictionary.

Lastly call the redraw passing the instance reference as the argument (not the definition reference.)