Explaining coordinate's calculation with map() - position

Could someone explain the meaning of this value/position: 300-400/2+10. I know it makes that the red circle won't go out of the square but I don't really understand the calculation..? Is there a page where I can read how it works because I personally would do it like this
float redCircle = map(mouseX,0,width,116,485);
circle(redCircle,map(mouseY,0,height,114,485),20);
with one number positions and not a calculation like in the code. I tried to understand it but I don't. I would really appreciate it if someone could explain the proceed.
void setup() {
size(600, 600);
surface.setTitle("Mapping");
surface.setLocation(CENTER, CENTER);
}
void draw() {
background(0);
stroke(255);
fill(255, 255, 255);//weißer Kreis
circle(mouseX, mouseY, 20);
mouseMoved();
text("Maus X/Y:"+mouseX+"/"+mouseY, 250, 300); //Text für weiße Position
fill(255, 0, 0); //Roter Kreis
float posFromMouseX = map(mouseX, 0, width, 300-400/2+10, 300-400/2+400-10);
float posFromMouseY = map(mouseY, 0, height, 300-400/2+10, 300-400/2+400-10);
ellipse(posFromMouseX, posFromMouseY, 20, 20);
text("map to: "+posFromMouseX+" / "+posFromMouseY, 255, 320); //Text für rote Position
// Transparentes Rechteck in der Mitte
noFill();
rect(300-400/2, 300-400/2, 400, 400);
}

map() will adjust the scale of a number accordingly to a range.
For an example, if you have these values:
MouseX: 200
width: 1000
You can easily calculate that, if the screen had a width of 2000 your mouse X position would need to be 400 to be proportional.
But this is an easy example. In the code you pasted here, the same thing is happening, but the coordinates compared are:
The whole window
The white rectangle
The map() function takes 5 args:
map(value, start1, stop1, start2, stop2)
value: float: the incoming value to be converted
start1: float: lower bound of the value's current range
stop1: float: upper bound of the value's current range
start2: float: lower bound of the value's target range
stop2: float: upper bound of the value's target range
So... you can totally write this line without the calculations:
float posFromMouseX = map(mouseX, 0, width, 110, 300-400/2+400-10);
// is the same thing than:
float posFromMouseX = map(mouseX, 0, width, 110, 490);
The probables reasons to write it that way are:
The author may not have wanted to do the simple math
The author may want to know where these numbers come from later (seeing how they were calculated would help on this front)
The author may want to change the hardcoded numbers for variables and make his white rectangle's size dynamic later
Hope it makes sense to you. Have fun!

Related

Why does the alpha value change when I have given it a constant value?

I am using the p5.js Web Editor
var sketch = function (p) {
with(p) {
p.setup = function() {
createCanvas(400, 400);
secCanvas = createGraphics(400, 400);
secCanvas.clear();
trans = 0;
drop_size = 10;
sun_size = 50;
radius = 10;
};
p.draw = function() {
background(3, 182, 252, 1);
image(secCanvas, 0, 0)
secCanvas.fill(255, 162, 0, 1)
secCanvas.ellipse(width/2, 0 + sun_size, sun_size)
fill(40, trans)
trans = random(255);
ellipse(random(mouseX + radius, mouseX - radius), random(mouseY + radius, mouseY - radius), drop_size)
drop_size = random(50)
};
}
};
let node = document.createElement('div');
window.document.getElementById('p5-container').appendChild(node);
new p5(sketch, node);
body {
background-color:#efefef;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.js"></script>
<div id="p5-container"></div>
When I set a discrete value of alpha in secCanvas.fill(). The value appears to be gradually increase(and stops soon), while I gave no such instruction. Why is this happening? This only happens when I put background(3, 182, 252, 1); in the draw function but not when I put it in the setup function.
Each frame is drawn on top of all previous frames, so when you draw a semi-transparent background, you can still see the previous frames underneath it.
Think of it as adding a very thin coat of paint over top what you've already painted. Because the color you're adding is semi-transparent, you can still see what's underneath it. Then during the next frame, you add another layer of paint, and the previous frames get just a little more faint.
They stop becoming more faint because of the way the computer calculates the new color, based on the previous frames and the new semi-transparent background color. Long story short, the color you're drawing is almost 100% transparent, so it's not strong enough to completely hide previous frames.

Color over color: how to get the resulting color?

I have the next task:
let's say, there are two colors: color1 and color2
color1 is semi-transparent (color2 maybe too)
I know ARGB values of color1 and color2
how to get the ARGB value of color which you get by overlaying color1 and color2 and vice versa?
Here is an image of what I am looking for:
And here is a code snippet (C#):
private Color getOverlapColor(Color frontColor, Color backColor)
{
//return...
}
The simplest way is to assume a linear scale.
int blend(int front, int back, int alpha)
=> back + (front - back) * alpha / 255;
And then:
Color getOverlapColor(Color front, Color back)
{
var r = blend(front.Red, back.Red, front.Alpha);
var g = blend(front.Green, back.Green, front.Alpha);
var b = blend(front.Blue, back.Blue, front.Alpha);
var a = unsure;
return new Color(r, g, b, a);
}
I'm unsure about how to calculate the resulting alpha:
if both front.Alpha and back.Alpha are 0, the resulting is also 0.
if front.Alpha is 0, the result is back.Alpha.
if front.Alpha is 255, the value of back.Alpha doesn't matter.
if front.Alpha and back.Alpha are both 50%, the result must be larger than 50%.
But I'm sure someone already figured out all of the above. Some SVG renderer, or GIMP, or some other image processing library should already have this code, carefully tested and proven in practice.

How do I draw 2D fonts in processing P3D mode?

I'm running a sketch with an array of points in 3D space (P3D). I'd like to add an interface to it by drawing text as if it were "onscreen"/2D, only using "X, Y" parameters.
When I tried just adding "text("!##$%", width/2, height/2);" it rendered in 3D space.
Is it possible? I tried "textMode(SCREEN) but doesnt exist in processing 2 anymore.
Here is what I found, I guess on the Processing Forum
You can use:
a PMatrix3D for your 3D content
and code your 2D stuff the plain old way
I wish it helps
PMatrix3D baseMat;
float alpha =0;
void setup() {
size(400, 400, P3D);
// Remember the start model view matrix values
baseMat = getMatrix(baseMat);
}
void draw() {
background(40);
pushMatrix();
camera(0, 0, 400, 0, 0, 0, 0, 1, 0);
directionalLight(255, 255, 255, -100, 150, -100);
ambientLight(40, 40, 40);
// 3D drawing stuff here
rotateY(alpha);
box(100);
alpha += 0.05;
popMatrix();
// Restore the base matrix and lighting ready for 2D
this.setMatrix(baseMat);
ambientLight(255, 255, 255);
// draw 2D stuff here
rect(10, 10, 50, 10);
textSize(25);
text("voila", mouseX, mouseY);
}
A workaround that comes to mind is to create a 2D PGraphic that has the same width/height as your sketch, give it a transparent background, draw your text where you want on it, and then draw the PGraphic onto your real sketch like you would if you were copying over image source data.

GDI: How to fill RoundRect with color?

While the question title seems dumb, that's not exactly what I need. To fill whole area with color, one needs to select appropriate brush - that's trivial. But I want to fill upper half of it with different color, and bottom half of it with the different one. If it was the normal (not round) rectangle, I could draw two rectangles (with different brushes). But with RoundRect I don't have any ideas how to do it.
Here is what I need it for: I draw each node in my graph visualization with RoundRect, and those nodes should have several compartments (cells) that should be filled with different colors.
I hope you get the idea what I mean :)
If you have to use legacy GDI instead of GDI+, here I wrote you a function to draw such a (cell) as you needed I hope it is what you have expected !
The basic idea is to create upper and lower regions (which they were both full overlapping rounded rectangles, then each has one of its halves cut off)
I have prepared the above illustration to show how the cell could be produced. It's for the upper side only, but you should have got the idea of creating the lower one.
Here is a wrapping function to create the cell you need:
void DrawCell(HDC& hdc, const RECT& rcTarget,const HBRUSH& hbrUpper, const HBRUSH& hbrLower)
{
HRGN hRgnUpper = CreateRoundRectRgn(rcTarget.left, rcTarget.top, rcTarget.right, rcTarget.bottom, 42, 38);
HRGN hRgnLower = CreateRoundRectRgn(rcTarget.left, rcTarget.top, rcTarget.right, rcTarget.bottom, 42, 38);
HRGN hRgnCutFromUpper = CreateRectRgn(rcTarget.left, rcTarget.top + ((rcTarget.bottom - rcTarget.top) / 2), rcTarget.right, rcTarget.bottom);
HRGN hRgnCutFromLower = CreateRectRgn(rcTarget.left, rcTarget.top , rcTarget.right, rcTarget.bottom - ((rcTarget.bottom - rcTarget.top) / 2));
CombineRgn(hRgnUpper, hRgnUpper,hRgnCutFromUpper, RGN_DIFF);
CombineRgn(hRgnLower, hRgnLower,hRgnCutFromLower, RGN_DIFF);
FillRgn( hdc, hRgnUpper, hbrUpper);
FillRgn( hdc, hRgnLower, hbrLower);
DeleteObject(hRgnCutFromLower);
DeleteObject(hRgnCutFromUpper);
DeleteObject(hRgnLower);
DeleteObject(hRgnUpper);
}
call this function from within your WM_PAINT handler:
RECT rcTarget;
rcTarget.left = 20;
rcTarget.top = 20;
rcTarget.right = 275;
rcTarget.bottom = 188;
HBRUSH hRed = CreateSolidBrush( RGB(255, 0, 0) );
HBRUSH hGreen = CreateSolidBrush( RGB(0, 255, 0) );
DrawCell(hdc, rcTarget, hRed, hGreen);

TCPDF: Clip text to Cell width

I am generating PDF report using TCPDF's Cell method extensively. Text printed with Cell method spills beyond width specified in method. I want to print only as much part of the text that fits in the specified width but not to spill beyond or wrap to next line. I do not want font stretch strategy.
I searched a lot but could not find a solution. Is there any other method/way to handle this?
(I used setfillcolor(255) to achieve the visual effect. But the text is still there, invisible; gets revealed when you try to select.)
here is my part of code.
$pdf->SetFillColor(255); // only visual effect
$pdf->Cell(36, 0, "A very big text in the first column, getting printed in 3.6cm width", 0, 0, 'L', true);
$pdf->Cell(20, 0, "Data 1", 0, 0, 'L', true);
$pdf->Cell(20, 0, "Data 2", 0, 0, 'L', true);
Thanks a lot.
I have found an answer here by Nicola Asuni, who is the main TCPDF author. The following code, provided by user fenstra, is working for me:
// Start clipping.
$pdf->StartTransform();
// Draw clipping rectangle to match html cell.
$pdf->Rect($x, $y, $w, $h, 'CNZ');
// Output html.
$pdf->writeHTMLCell($w, $h, $x, $y, $html);
// Stop clipping.
$pdf->StopTransform();
As far as I can tell, the clipping rectangle won't consider any padding on the displayed text, so you apply the proper math to Rect's width and height if you need to mimic the behaviour of a MultiCell on this particular.
For this one I created it with cell and make function on it to call it globally
* clip Text
*
* #param float $w width
* #param float $h height
* #param float $x x-axis
* #param float $y y-axis
* #param string $str text
*
* #return void
*/
private function clipText($w, $h, $x, $y, $str)
{
// Start clipping.
$this->Pdf->StartTransform();
// Draw clipping rectangle to match cell.
$this->Pdf->Rect($x, $y, $w, $h, 'CNZ');
// Output text.
$this->Pdf->SetXY($x, $y);
$this->Pdf->Cell($w, $h, $str, 0, 0, 'L', 0, 0);
// Stop clipping.
$this->Pdf->StopTransform();
}

Resources