Polygon Area Calculations Differences Using MatLab's Polyarea to Excel's SumProduct - excel

I am calculating the area enclosed by this polygon:
Given by a set of coordinates:
0 2.06667
1.14815 2.06667
3.44444 2.75556
5.74074 3.44444
9.18519 3.44444
16.0741 2.75556
26.4074 1.83704
35.5926 1.14815
38.2333 0.688889
38.75 0.028704
I originally did this in Excel, using the Sumproduct method, and got an answer which seemed reasonable. The Excel formula I'm using is:
=0.5*ABS(SUMPRODUCT(F30:F39,G31:G40)-SUMPRODUCT(G30:G39,F31:F40))
with F30:G40:
0 2.06667
1.14815 2.06667
3.44444 2.75556
5.74074 3.44444
9.18519 3.44444
16.0741 2.75556
26.4074 1.83704
35.5926 1.14815
38.2333 0.688889
38.75 0.028704
0 0
And the result is 87.74.
After moving to Matlab, I started using the polyarea and the answer looks unreasonable. The problematic code is:
Shape = [ 0 2.0667; 1.1482 2.0667; 3.4444 2.7556; 5.7407 3.4444; 9.1852 3.4444; 16.0741 2.7556;26.4074 1.8370; 35.5926 1.1482; 38.2333 0.6889; 38.7500 0.0287]
C = polyarea(Shape(:,1),Shape(:,2))
With the returned answer:
C =
47.6986
I have tried playing around with the order of points as one answer suggests here as well as adding the final points into the end (can't find the link again), but that does not seem to make a whole lot of difference.
One answer suggested using convhull for the maximum enclosed area, but that returned 50.34 with the Shape as it is currently defined.
So, my question is: how should this calculation be performed to get the correct result? The Excel-provided values look more correct to me based on the graph, but I am uncertain what I'm doing incorrectly in MatLab based on the help and advice I have investigated. If the error is in my Excel code, that would also be good to know.

You didn't close the polygon!
C = polyarea([Shape(:,1); 0],[Shape(:,2); 0])
C =
87.740954125
Matlab will not assume that (0,0) is in the polygon unless you explicitly state it!

Related

Visual Python using a for loop to track a changing axis?

I have a giant array that I am importing from a text file holding 200,000 values which all describe how an arrow should be traversing along the x axis. Mx is the name of the array that I have imported from this text file. I am using visual python to try and simulate this movement across the axes.
arrow = arrow(length = 1.0,pos = (0,0,0),axis=(0,0,0),color=color.blue)
for i in range(len(Mx)):
rate(60)
arrow.axis.x = Mx[i]
When I run my code the arrow remains stationary, and "QObject::killTimers: timers cannot be stopped from another thread" this error message pops up. I am not sure why. Any advice would be really helpful.
What I found is that this fixed it for some reason.
arrow = arrow(length = 1.0,pos = (0,0,0),axis=(0,0,0),color=color.blue)
for i in range(len(Mx)):
rate(60)
x = Mx[i]
arrow.axis.x = x
Not 100 percent sure why, but I am guessing it has something to do with how python handles the array that I imported from the text file.

Setting multiple axvspan labels as one element in legend

I am trying to set up a series of vertical axis spans to symbolize different switching positions at different times. For example, in the figure below, switching position 1 (green) happens quite a few times, alternating between other positions.
I plot these spans running a for loop in a list of tuples, each containing the initial and final indexes of each interval to plot the axvspan.
def plotShades(timestamp, intervals, colour):
for i in range(len(intervals)):
md.plt.axvspan(timestamp[intervals[i][0]], timestamp[intervals[i][1]], alpha=0.5, color=colour, label="interval")
This function is then called upon another one, that plots the shades for each different switching position:
def plotAllOutcomes(timestamp, switches):
#switches is a list of 7 arrays indicating when the switcher is at each one of the 7 positions. If the array has a 1 value, the switcher is there. 0 otherwise.
colors = ['#d73027', '#fc8d59', '#fee08b', '#ffffbf', '#d9ef8b', '#91cf60', '#1a9850']
intervals = []
for i in range(len(switches)):
intervals.append(getIntervals(switches[i], timestamp))
plotShades(timestamp, intervals[i], colors[i])
md.plt.legend()
Doing so with the code snippets I've put here (not the best code, I know - I'm fairly new in Python!) the legend ends up having one item for each interval, and that's pretty awful. This is how it looks:
I'd like to get a legend with only 7 items, each for a single color in my plot of axvspans. How can I proceed to do so? I've searched quite extensively but haven't managed to find this situation being asked before. Thank you in advance for any help!!
A small trick you can apply using the fact that labels starting with "_" are ignored:
plt.axvspan( ... , label = "_"*i + "interval")
Thereby a label is only created for the case where i==0.

Matlab - Using symbols in gscatter

Ok, so I'm trying to use gscatter to plot 8 different points in a figure. These 8 points are all different and thus I want to give them different symbols. I know that gscatter will automatically assign them different colors, but I also want to be able to use the figure in black and white. I have written the following code:
lincol = {'k';'k';'k';'k';'k';'k';'k';'k'};
linsym = {'+';'o';'*';'.';'x';'s';'d';'^'};
limits = [-1 1 -1 1];
close all
for i = 1:3;
figure(i); hold on
gscatter(RfootXdistpertRel(:,i),RfootYdistpertRel(:,i),lincol,linsym);
legend('Pert1', 'Pert2', 'Pert3', 'Pert4', 'Pert5', 'Pert6', 'Pert7', 'Pert8')
hline(0);
vline(0);
axis(limits);
end
According to the matlab syntax, I should be able to specify color and marker symbol in this way (gscatter(x,y,col,sym)). The variables used are 8 by 1 vectors, just as the lincol and linsym. However, it gives me an error:
Error using plot
Color value must be a 3 or 4 element vector
Can anyone help? It's just such a silly problem to have.
Luc
It seems that you have some errors in your code. The syntax for gscatter should include at least 3 parameters : x, y and group. It seems that group is missing.
Furthermore the definition of color and sym may be wrong. Try col = 'kkkkkkkk'; instead of lincol = {'k';'k';'k';'k';'k';'k';'k';'k'};.
I hope this helps.
Regards.
Jonay

Bumpy jigsaw type data into curve data

I have a problem I solved in Excel but I am completely stuck in Matlab.
A weight measuring how much liquid I pump is refilled when its almost empty. Here is a picture
Now I want to see it in one motion, not like a jigsaw. Here is my solution, doing it manually in Excel:
Now to Matlab where this should be done automatically: I know how to index the row before and after I have the bumps, but I'm kind of stuck now. I do d=diff(x) ok and now I can replace the high peaks when the bumps occur (i=d(:,1)>0) with 0 so it never happened. And how do I translate it back? Somehow "undiff(x)"? im completely lost.
Here's an extract of my x:
2533,30
3540,00
3484,90
3430,00
3375,00
3320,20
3265,60
3210,60
3155,80
3101,20
3046,50
2991,70
2937,00
2882,50
2828,10
2773,80
2719,30
2664,90
2610,50
2556,10
2501,60
3508,00
3454,00
3399,70
3352,10
Like this?
temp = [0; diff(x)];
temp(temp < 0) = 0;
y = x - cumsum(temp);
y(temp > 0) = interp1(y, find(temp > 0) + 0.5);
plot(y);
hen using the default plot() function, matlab will automatically draw a line plot and connect each point in the data you are plotting.
Instead it seems like you just need to plot the points individually and unconnected. So if you are currently doing something like plot(x) or area(x) instead try plot(x,'o'). This will cause Matlab to plot the points individually without connecting them as lines.
If you'd like to change the marker type used to plot each point, use doc linespec to get more info.

How to encircle Invalid data in Excel?

I want to show a circle around only invalid data.
i have done the complete steps shown in this link
But this circle shown is very big and covers the entire cell.
I want a small circle only covering the data not the entire cell's width.
Data validation is a built in Excel functionality. It checks whole cell value.
So it is not possible, using Data validation, to accomplish what your trying.
It MAY BE POSSIBLE using VBA, shapes, events and (hard) parsing character rendering. In your place, I would be glad with this very big circles!!! :)
I agree with #LS_dev. See this MS Article about changing data validation for printing. Try modifying it to loop through all your data validation and change the width and height.
You can probably do it with this part of the code by changing the width and height:
If Not c.Validation.Value Then
Set o = ActiveSheet.Shapes.AddShape(msoShapeOval, _
c.Left - 2, c.Top - 2, c.Width + 4, c.Height + 4)
o.Fill.Visible = msoFalse
o.Line.ForeColor.SchemeColor = 10
o.Line.Weight = 1.25

Resources