Since Sketchup 14 there is a new API function
add_dimension_linear
see
http://www.sketchup.com/intl/en/developer/docs/ourdoc/entities#add_dimension_linear
In trying to understand and use it I have looked for some examples and discussions at:
http://forums.sketchup.com/t/adding-dimensions-to-a-line-with-ruby/1158
http://sketchucation.com/forums/viewtopic.php?f=15&t=62331
the offeset_vector parameter is described in the API reference as:
the parallel offset vector from the reference line to the dimension line measured from the 'start' reference point.
In the example e.g.
dim = entities.add_dimension_linear edge, mp, cp, [20, 0, 0]
the Vector is 20,0,0.
How is this Vector to be chosen?
This vector just indicates how far and in which direction you want to offset the dimension line so that it doesn't overlap with whatever entity you are dimensioning. So the exact choice of direction and offset amount depends on the situation.
Try pasting this code into the Ruby Console, for instance:
entities = Sketchup.active_model.entities
dim = entities.add_dimension_linear [50, 10, 0], [100, 10, 0], [0, 20, 0]
You'll see that the dimension leader lines are in y-direction, because the vector is specified as [0, 20, 0]
Related
I'm trying to implement in Elixir some of the maze generation algorithms from the excellent book Mazes for Programmers by Jamis Buck. In imperative languages like Go or V it's a piece of cake but with Elixir I'm stuck.
A maze is a grid of cells. A cell holds information about in which direction we can move. It is represented as a struct with boolean members (north: true or east: false, etc.). A grid is a map where keys are tuples {col, row} and values are Cells. If mz is a maze, mz.grid[{0, 0}] is the cell located at the upper left corner.
One of the basic operation is to open a path from one cell c1 to another c2 and most of the time, if we can go from c1 to c2, we can also go from c2 to c1 which means this operation modifies both cells. To implement this, I have a function open_to(maze, x, y, direction) which returns a tuple of two cells c1_new and c2_new where the direction information in each cell had been changed. Then I can update the grid with Enum.put(maze.grid, {x, y}, c1_new). Same for c2_new.
One of the most simple algorithm, the binary tree algorithm, needs to visit all cells one by one and open a bidirectional link with one of the neighbors. Bidirectional means that both cells need to be updated and the second cell may be visited only later. I'm stuck at this step as I can't find how to update the grid with the cells returned by open_to(). My Elixir pseudo code is as follows:
def generate(mz) do
Enum.map(mz.grid, fn({{x, y}, c1}) ->
neighbors = [Grid.cell_to(mz, x, y, :north), Grid.cell_to(mz, x, y, :east)]
c2_dir = select_the_neighbor(neighbors) # returns one of :north, :east or nil
# Here! open_to returns the updated cells but what to do with them?
{c1_new, c2_new} = if c2_dir != nil, do: Grid.open_to(mz, x, y, c2_dir)
end)
end
I believe the issue comes from the data structure I've chosen and from the way I go through it, but I can't find another way. Any help is appreciated
If I'm understanding the question it's "how can each step in Enum.map/2 update the maze and have that visible to each other and the final result?".
Where data structures in Elixir are immutable, you don't change the data another variable points to.
As a simple example, putting a key/value pair into a map creates an entirely new map:
iex(1)> map = %{a: 3}
%{a: 3}
iex(2)> Map.put(map, :a, 4)
%{a: 4}
iex(3)> map
%{a: 3}
In a similar fashion, Enum.map/2 isn't intended for modifying anything except the value currently being operated on (and even then only in the new list, not the original). If you want to update some value based on each cell you may be looking for Enum.reduce/3. It enumerates things like Enum.map/2, but it takes a value or "accumulator". The reducer function you pass in is called with an item and the accumulator and ought to return the updated value of the accumulator. Then the final value of that accumulator is what is returned from Enum.reduce/3.
So your pseudo code might look something like this:
def generate(mz) do
# don't use the c1 from enumerating the grid--it could be out of date
# you could also just enumerate the grid coordinates:
# - for x <- 0..width-1, y <- 0..height-1, do: {x, y}
# - Map.keys(mz.grid)
Enum.reduce(mz.grid, mz, fn {{x, y}, _dont_use_this_c1}, mz ->
neighbors = [Grid.cell_to(mz, x, y, :north), Grid.cell_to(mz, x, y, :east)]
if c2_dir = select_the_neighbor(neighbors) do
{c1_new, c2_new} = Grid.open_to(mz, x, y, c2_dir)
mz
|> Map.put({x, y}, c1_new)
|> Map.put(find_x_y(x, y, c2_dir), c2_new)
else
# you have to return a maze, or other iterations will try adding cells to nil
mz
end
end)
end
I have a very large array (RFO_2003; dim = c(360, 180, 13, 12)) of numeric data. I made the array using a for-loop that does some calculations based another array. I am trying to check some samples of data in this array to ensure I have generated it properly.
To do this, I want to apply a function that returns the index of the array where that element equals a specific value. For example, I want to start by looking at a few examples where the value == 100.
I tried
which(RFO_2003 == 100)
That returned (first line of results)
[1] 459766 460208 460212 1177802 1241374 1241498 1241499 1241711 1241736 1302164 1302165
match gave the same results. What I was expecting was something more like
[8, 20, 3, 6], [12, 150, 4, 7], [16, 170, 4, 8]
Is there a way to get the indices in that format?
My searches have found solutions in other languages, lots of stuff on vectors, or the index is never output, it is immediately fed into another part of a custom function so I can't see which part would output the index in a way I understand, such as this question, although that one also returns dimnames not an index.
Suppose I have an array where some values are NaN. For example [1, 2, NaN, 4].
Is there any Julia library that able to fill the array with interpolated values?
So that the result would be [1, 2, 3, 4].
I can not see if I am able to do it with Interpolations.jl.
For now, I am not concerned with the interpolation function. I just need to fill this linearly.
Thanks in advance.
You can just do it yourself, as long as it is not an edge case, find the next and previous value and take the average.
I need to pull a vector from a normal distribution and normalize it to sum 0, because I want to simulate the power with the pwr.rasch() function from the pwrRasch package. Sounds easy enough.
I create the vector like this:
set.seed(123)
itempars <- rnorm(n = 10, mean = 0, sd = 1.8)
To normalize the parameters to 0, I subtract the sum of my vector off of the last element of the vector like this:
itempars[10] <- itempars[10] - sum(itempars)
When I type sum(itempars) it should be 0, but it's -8.326673e-17. How is it possible? How can I get it to 0? I tried to round already, but it only increases the sum.
I don't want to choose every Itemparameter by hand. Thanks in advance!
EDIT:
Obviously the reasion is floating-point arithmetic. But it's hard to imagine that there is no way around.
The error massage of pwr.rasch() is as follows:
Error in simul.rasch(eval(parse(text = ppar[[1]])), ipar[[1]]) :
Item pararameters are not normalized to sum-0
Sadly, the function has poor documentation. When I estimate groupwise itemparameters with eRm's RM() function, which has an extra argument for normalizing to sum 0, it gives me a similar difference like in my example.
Any trick'd come in handy as I don't want to create more than 50 normal distributed itemparameters per hand. Even worse. If I understood floating-point arithemtic corretly this problem can appear with the use of doubles in general. It'd be extremely limitating if I'd only be able to use integers as itemparameters.
I downloaded the source code of the pwrRasch package and changed the if condition from
if (all(round(unlist(lapply(ipar, sum)), 3) != 0)) {
stop("Item pararameters are not normalized to sum-0")
}
to
if (all(round(unlist(lapply(ipar, sum)), 3) > 1e-5)) {
stop("Item pararameters are not normalized to sum-0")
}
I would like to convert a for cycle into a faster operation such as apply.
Here is my code
for(a in 1:dim(k)[1]){
for(b in 1:dim(k)[2]){
if( (k[a,b,1,1]==0) & (k[a,b,1,2]==0) & (k[a,b,1,3]==0) ){
k[a,b,1,1]<-1
k[a,b,1,2]<-1
k[a,b,1,3]<-1
}
}
}
It's a simple code that does a check on each element of the multidimensional array k and if the three elements are the same and equal to 0, it assigns the value 1.
Is there a way to make it faster?. The matrix k has 1,444,000 elements and it takes too long to run it. Can anyone help?
Thanks
With apply you can return all your 3-combinations as a numeric vector and then check for your specific condition:
# This creates an array with the same properties as yours
array <- array(data = sample(c(0, 1), 81, replace = TRUE,
prob = c(0.9, 0.1)), c(3, 3, 3, 3))
# This loops over all vectors in the fourth dimension and returns a
# vector of ones if your condition is met
apply(array, MARGIN = c(1, 2, 3), FUN = function(x) {
if (sum(x) == 0 & length(unique(x)) == 1)
return(c(1, 1, 1))
else
return(x)
})
Note that the MARGIN argument specifies the dimensions over which to loop. You want the fourth dimension vectors so you specify c(1, 2, 3).
If you then assign this newly created array to the old one, you replaced all vectors where the condition is met with ones.
You should first use the filter function twice (composed), and then the apply (lapply?) function on the filtered array. Maybe you can also reduce the array, because it looks like you're not very interested in the third dimension (always accessing the 1st item). You should probably do some reading about functional programming in R here http://adv-r.had.co.nz/Functionals.html
Note I'm not a R programmer, but I'm quite familiar with functional programming (Haskell etc) so this might give you an idea. This might be faster, but it depends a bit on how R is designed (lazy or eager evaluation etc).