Search code examples
excelmatlabcell-array

How can I apply mathematical calculation for every Elements of a Cell Array ( like in Excel)


Friends,

I have two following Cell arrays (or two Excel-Tables, if necessary).

Cell array for the Bodies

[Body]     [Weigh]  [warranty]
[A1]        [3.5]     [2]
[A2]        [6.2]     [3]
[B1]        [7.1]     [1]
[B2]        [3.9]     [4]
[B3]        [4.2]     [5]
[C1]        [1.3]     [7]
...         ....     ...

Cell array for the partial Objects in each Body

   [Object] [x_min] [x_max] [y_min] [y_max] [Volume]
   [A1-a1]   [5.7]   [7.3]   [8.9]   [4.3]   [5.1]
   [A1-a2]   [2.6]   [5.6]   [9.3]   [5.7]   [5.2]
   [A1-a3]   [3.6]   [7.3]   [5.3]   [7.3]   [5.8]
   [A2-a1]   [8,2]   [5.8]   [2.7]   [5.3]   [6.3]
   [A2-a2]   [8.4]   [6.3]   [8.5]   [6.3]   [9.3]
   [B1-b1]   [7.1]   [6.3]   [8.2]   [8.5]   [5.3]
   [B1-b2]   [8.9]   [8.4]   [4.5]   [6.2]   [4.5]
   [C1-c1]   [7.0]   [7.1]   [1.3]   [8.9]   [1.3]
   [C1-c2]   [6.9]   [4.8]   [3.2]   [9.2]   [3.7]
   [C1-c3]   [5.3]   [2.5]   [4.2]   [6.4]   [6.3]
    ...       ...     ...     ...     ...     ...

I would like to write a program, which does the following steps to the objects automatically:

  1. Calculate the weight of each object according to the formula:

    Weigh_obj = Weigh_body * Volume_obj / Sum of every Volume_obj in the body
    

for example

Weigh_A1-a1 = Weigh_A1 * Volume_A1-a1 / (Volume_A1-a1 + Volume_A1-a2 + Volume_A1-a3)
            = 3.5 * 5.1 / (5.1+5.2+5.8)
  1. Compare the coordination of each object with the coordination of the other objects to find out, if there is a Touch between any two objects:

For example, with two Objects Object1 and Object2:

if  ( (x2_min <=x1_min<=x2_max)or(x2_min <=x1_max<=x2_max)...
   and (y2_min <=y1_min<=y2_max)or(y2_min <=y1_max<=y2_max) )

    % returns '1' in corresponding positions in the square matrix of `n` objects, like this: 

    [ X]  [O1] [O2] [O3] ... [O_n]
    [O1]  [X]  [1]  [ ]  ... 
    [O2]  [1]  [X]  [ ]  ... 
    [O3]  [ ]  [ ]  [X]  ... 
    ...   ...  ...  ...  [X]
    [On]  ...  ...  ...  ... [X]  


 else
     returns '0' in the corresponding Positions in the matrix
 end

so that in the end I get a full filled Object-matrix

I hope that I have explained my problem clear enough.

Thanks in advance!


thanks a lot for your help !

For the 1) step: collsion detection : I want to detect the colosion between any two objects in the 2nd table .i.e. not only A1-a1 with A1-a2... but also A1-a1 with B1-b1..., C1-c1... and so on. After that i want to buil a matrix like this

[ X]      [A1-a11] [A1-a2] [A1-a3] ...  [B1-b1] [B1-b2] [C1-c1]
[A1-a1]   [X]       [ ]     [ ]   ...      [ ]    [ ]     [ ] 
[A1-a2]   [ ]       [X]     [ ]   ... 
[A1-a3]   [ ]       [ ]      [X]   ... 
...       ...       ...      ...   [X]
[B1-b1]   ...       ...      ...   ...      [X]  
[B1-b2]
[C1-c1]   ...       ...      ...   ...      ..     ...     [X]

and fillthe matrix with the result of the collsion detection. Would you have any idea ?

For the 2) Step, you have made it exactlty what I need. But here we dont find the density of the objets. We just find the weigh of the object. Because you calculated "specific volume" with the formular:

    [object volume / total body volume] = [m^3 / m^3] = [1] (no unit, just a quote)

and finally [ body weight * specificVolumes]=[kg * 1] = [kg] = [weigh] of object

Regards !


Solution

  • If I understand you correctly, you want to do collision detection and compute the densities of individual objects.

    Believe it or not, the collision detection is a lot easier to do than the volume calculation. This is mostly due to how your data is organized.

    Here's what I arrived at:

    % [Body]     [Weight]  [warranty]
    Bodies = {...
        'A1'      3.5      2
        'A2'      6.2      3
        'B1'      7.1      1
        'B2'      3.9      4
        'B3'      4.2      5
        'C1'      1.3      7
    };
    
    %   [Object]  [x_min] [x_max] [y_min] [y_max] [Volume]
    Objects = {...
        'A1-a1'   5.7     7.3     8.9     4.3     5.1
        'A1-a2'   2.6     5.6     9.3     5.7     5.2
        'A1-a3'   3.6     7.3     5.3     7.3     5.8
        'A2-a1'   8.2     5.8     2.7     5.3     6.3
        'A2-a2'   8.4     6.3     8.5     6.3     9.3
        'B1-b1'   7.1     6.3     8.2     8.5     5.3
        'B1-b2'   8.9     8.4     4.5     6.2     4.5
        'C1-c1'   7.0     7.1     1.3     8.9     1.3
        'C1-c2'   6.9     4.8     3.2     9.2     3.7
        'C1-c3'   5.3     2.5     4.2     6.4     6.3
    };
    
    % Rename variables for clarity
    BodyNames = Bodies(:,1);
    Weights =  cat(1, Bodies{:,2});
    
    ObjectNames = Objects(:,1);
    x_min  = [Objects{:,2}].';
    x_Max  = [Objects{:,3}].';
    y_min  = [Objects{:,4}].';
    y_Max  = [Objects{:,5}].';
    Volume = [Objects{:,6}].';
    
    % Find densities
    % --------------------
    
    % find which objects belong to which bodies
    ObjInds = cellfun(@(x) regexp(ObjectNames, x), BodyNames, 'UniformOutput', false);
    ObjInds = cellfun(@(x) ~cellfun('isempty', x), ObjInds, 'UniformOutput', false);
    
    % Compute the specific volumes (object volume / total body volume)
    specificVolumes = cellfun(@(x) Volume(x) ./ sum(Volume(x)), ObjInds, 'UniformOutput', false);
    
    % Compute densities (= body weight * specificVolumes)
    densities = cellfun(@(x,y)x.*y, num2cell(Weights), specificVolumes, 'UniformOutput', false);
    densities = cat(1, densities{:});
    
    
    % Collsion detection 
    % --------------------
    
    % This is it: 
    Colissions = ...
        bsxfun(@le, x_min, x_Max') & bsxfun(@ge, x_min, x_min') & ...
        bsxfun(@le, y_min, y_Max') & bsxfun(@ge, y_min, y_min');
    

    Now, the above collision detection will give some "odd" results. This is due to the fact that some of your x_min > x_max and some y_min > y_max. This is easily corrected with a sort() or similar, but I'll leave that up to you.