GDI+ draws internal lines in a polygon path - gdi+

I am trying to paint a following polygon:
with this code:
procedure TForm1.Paint;
var
g: TGPGraphics;
pen: TGPPen;
i: Integer;
p: TGPGraphicsPath;
m: TGPMatrix;
br: TGpSolidBrush;
begin
inherited;
g := TGPGraphics.Create(Canvas.Handle);
pen := TGPPen.Create(MakeColor(141, 63, 0), 3);
p := TGPGraphicsPath.Create();
m := TGPMatrix.Create;
br := TGpSolidBrush.Create(MakeColor(244, 146, 32));
try
g.SetSmoothingMode(SmoothingModeHighQuality);
g.Clear(MakeColor(255, 255, 255));
g.TranslateTransform(ClientWidth div 2, ClientHeight div 2);
m.Rotate(45);
p.StartFigure;
for i := 0 to 7 do begin
p.AddLine(-14, -33, 0, -55); // To upper right
p.AddLine(0, -55, 14, -33); // To lower right
p.Transform(m); // Rotate by 45 degree
end;
p.CloseFigure;
g.DrawPath(pen, p);
finally
br.Free;
m.Free;
p.Free;
pen.Free;
g.Free;
end;
end;
but GDI+ closes every star ray path, and produces following painting:
What is wrong here?
P.S.: I have to use the AddLine method, each call with two coordinates, to paint two sides of a ray. Is there some method like LineTo, with only one pair of X and Y, that takes the last point as the beginning?
Or is there some method to transform a TGPPointF by rotating around some other point, without actually painting it?

The problem was solved by rotating in the other direction:
m.Rotate(-45);
It seems that it paints the left side of a ray, then the right side, but when it rotates by positive number, it rotates counter clockwise, so the next ray will be on the left side of the previous one ... Strange.

Related

How to determine if need to swap start and end angle when drawing an arc

I have multiple polygon maps (made up of lines and arcs). I am using turf.lineArc() to calculate points on an arc and to do this the start and end points of the arc need to be clockwise, if not they need to be swapped around.
I have the following code to swap the start and end points around (but it is not quite right)
if (endAngle < startAngle) {
endAngle = endAngle + 360;
}
if (startAngle < endAngle) {
var e = endAngle;
endAngle = startAngle;
startAngle = e;
}
while (startAngle - endAngle > 180) {
startAngle = startAngle - 360;
}
var arc = turf.lineArc(center, radius, startAngle, endAngle, options);
My problem is knowing when to swap the start and end around and when not to. In my attached picture Map1 works correctly without being swapped around but Map2 needs to have the start and end points swapped. (and they both need to use the same code). If map 2 does not have the start and end swapped around turf.lineArc draws a major arc of 353 degrees which is not what I want.
How do I fix my code so I only swap the start and end points when travelling from start to end is in an anti-clockwise direction?
Thank you :)
Edit: Arc can be < 180 or >180 and I know if it is major (>180) or minor (<180)
If your desired arc always should be < 180 degrees, then you can apply the next approach to overcome periodicity and zero-crossing pitfalls:
if Math.sin(endAngle-startAngle) < 0 then swap
I think, angles should be in radians in turfjs.
Also check - perhaps you have to change <0 to >0 to provide clockwise direction in your coordinate system.
I used this by Corrl to determine clockwise direction so then knew if to swap or not.
JavaScript - Find turn direction from two angles

Advanced rectangles collision in processing

Coded in procesing (processing.org):
I want to know when the mouse or another shape collides with a rectangle,
this is very easy but I have one problem: I want it to work when the rectangle is rotated (example: rotate(radians(90))).
Both Kevin and Asad's contributions are useful.
In terms of using the 2D renderer, you need to roll your own functionality for that. For this you should be familiar with a few bits and bobs of linear algebra (vector and matrices mainly and just a few operations anyway).
I am going to assume you're already familiar with 2D transformations (using pushMatrix()/popMatrix() along with translate(),rotate(),scale()) if not, I warmly recommend the 2D Transformations Processing tutorial
I am going to explain some of the concepts only briefly (as it's a big topic on it's own).
If you used translate()/rotate()/scale() before, it's all been matrix operations handled for you behind the scenes. In 2D, a transformation can be stored in a 3x3 matrix like so:
X Y T
1 0 0
0 1 0
0 0 1
The rotation and scale are stored in the 1st and 2nd column (2 values each) while translation is stored in the last column. In theory you could have a 2x3 matrix instead of a 3x3 matrix, but an NxN matrix has a few nice properties. One of the nice things is being simple to multiply with a vector. Position can be stored as vectors and we'd like to transform a vector by multiplying it with a transformation matrix. If you look at a vector as a single column vector, the 3x3 form of the matrix allow multiplication(see matrix multiplication rules here).
In short:
You can store transformations in a matrix
You can apply these transformation to a vector using multiplication
Back to your issue, checking if a point is within a box with transformations applied, you can do this:
convert the test point's coordinate system to the box's transformed coordinate system by:
inverting the box's transformation matrix and
multiplying the point to the inverted transformation matrix.
This may be hard to comprehend at first, but one way to look at is imagining you rotate the whole 'world'(coordinate system) so your rotated box is straight (essentially rotating in the opposite direction, or inverting the transformation) then check if the point is in the box.
Luckily all these matrix operations don't need to be implemented from scratch: PMatrix2D deals with this.
Here is a basic commented sketch explaining all the above:
Box box1,box2;
void setup(){
size(400,400);
box1 = new Box(200,100);
box1.translate(75,100);
box1.rotate(radians(30));
box1.scale(1.1);
box2 = new Box(100,200);
box2.translate(275,150);
box2.rotate(radians(-5));
box2.scale(.95);
}
void draw(){
background(255);
box1.update(mouseX,mouseY);
box2.update(mouseX,mouseY);
box1.draw();
box2.draw();
}
class Box{
PMatrix2D coordinates = new PMatrix2D();//box coordinate system
PMatrix2D reverseCoordinates = new PMatrix2D();//inverted coordinate system
PVector reversedTestPoint = new PVector();//allocate reversed point as vector
PVector testPoint = new PVector();//allocate regular point as vector
float w,h;//box width and height
boolean isHovered;
Box(float w,float h){
this.w = w;
this.h = h;
}
//whenever we update the regular coordinate system, we update the reversed one too
void updateReverseCoordinates(){
reverseCoordinates = coordinates.get();//clone the original coordinate system
reverseCoordinates.invert();//simply invert it
}
void translate(float x,float y){
coordinates.translate(x,y);
updateReverseCoordinates();
}
void rotate(float angle){
coordinates.rotate(angle);
updateReverseCoordinates();
}
void scale(float s){
coordinates.scale(s);
updateReverseCoordinates();
}
boolean isOver(float x,float y){
reversedTestPoint.set(0,0);//reset the reverse test point
testPoint.set(x,y);//set the x,y coordinates we want to test
//transform the passed x,y coordinates to the reversed coordinates using matrix multiplication
reverseCoordinates.mult(testPoint,reversedTestPoint);
//simply test the bounding box
return ((reversedTestPoint.x >= 0 && reversedTestPoint.x <= w) &&
(reversedTestPoint.y >= 0 && reversedTestPoint.y <= h));
}
void update(float x,float y){
isHovered = isOver(x,y);
}
void draw(){
if(isHovered) fill(127);
else fill(255);
pushMatrix();
applyMatrix(coordinates);
rect(0,0,w,h);
popMatrix();
}
}
You're looking for the modelX() and modelY() functions. Just pass in mouseX and mouseY (z is 0) to find the position of the mouse in rotated space. Similarly, pass in the position of your rectangles to find their rotated points.
Here's the example from the reference:
void setup() {
size(500, 500, P3D);
noFill();
}
void draw() {
background(0);
pushMatrix();
// start at the middle of the screen
translate(width/2, height/2, -200);
// some random rotation to make things interesting
rotateY(1.0); //yrot);
rotateZ(2.0); //zrot);
// rotate in X a little more each frame
rotateX(frameCount / 100.0);
// offset from center
translate(0, 150, 0);
// draw a white box outline at (0, 0, 0)
stroke(255);
box(50);
// the box was drawn at (0, 0, 0), store that location
float x = modelX(0, 0, 0);
float y = modelY(0, 0, 0);
float z = modelZ(0, 0, 0);
// clear out all the transformations
popMatrix();
// draw another box at the same (x, y, z) coordinate as the other
pushMatrix();
translate(x, y, z);
stroke(255, 0, 0);
box(50);
popMatrix();
}

THREE.js: Why is my object flipping whilst travelling along a spline?

Following up from my original post Three.JS Object following a spline path - rotation / tangent issues & constant speed issue, I am still having the issue that the object flips at certain points along the path.
View this happening on this fiddle: http://jsfiddle.net/jayfield1979/T2t59/7/
function moveBox() {
if (counter <= 1) {
box.position.x = spline.getPointAt(counter).x;
box.position.y = spline.getPointAt(counter).y;
tangent = spline.getTangentAt(counter).normalize();
axis.cross(up, tangent).normalize();
var radians = Math.acos(up.dot(tangent));
box.quaternion.setFromAxisAngle(axis, radians);
counter += 0.005
} else {
counter = 0;
}
}
The above code is what moves my objects along the defined spline path (an oval in this instance). It was mentioned by #WestLangley that: "Warning: cross product is not well-defined if the two vectors are parallel.".
As you can see, from the shape of the path, I am going to encounter a number of parallel vectors. Is there anything I can do to prevent this flipping from happening?
To answer the why question in the title. The reason its happening is that at some points on the curve the vector up (1,0,0) and the tangent are parallel. This means their cross product is zero and the construction of the quaternion fails.
You could follow WestLangley suggestion. You really want the up direction to be the normal to the plane the track is in.
Quaternion rotation is tricky to understand the setFromAxisAngle function rotates around the axis by a given angle.
If the track lies in the X-Y plane then we will want to rotate around the Z-axis. To find the angle use Math.atan2 to find the angle of the tangent
var angle = Math.atan2(tangent.y,tangent.x);
putting this together set
var ZZ = new THREE.Vector3( 0, 0, 1 );
and
tangent = spline.getTangentAt(counter).normalize();
var angle = Math.atan2(tangent.y,tangent.x);
box.quaternion.setFromAxisAngle(ZZ, angle);
If the track leaves the X-Y plane things will get trickier.

Gothic pointed arch css or canvas

i wonder if someone knows a source or a way to design a Gothic pointed arch with css or canvas.
Edit:
My attempt was to style the canvas quadraticCurveTo method to fit the gothic arc. But I failed badly and had not the guts to post it here :)
var canvas = document.getElementById('arch');
var context = canvas.getContext('2d');
context.beginPath();
context.moveTo(188, 150);
context.quadraticCurveTo(288, -100, 388, 150);
context.lineWidth = 20
context.strokeStyle = 'black';
context.stroke();
http://jsfiddle.net/zumgugger/ZaqJ5/
Just because this is quirky and interesting....
Some geometry for a gothic pointed arch can be found here :
Perhaps the most recognizable feature of gothic architecture is the pointed arch. The basic gothic arch is equilateral in construction and forms the basis of many variants.
The construction of the equilateral arch is thus:
From the drawing, the compass is set to the span, a-b. With x-y as the springing line, the compass is positioned at the junction of a-x/y and a curve from x/y-q is draw as shown. The procedure is repeated with the compass placed at the junction of b-x/y, with the point at which the curves join forming the rise p-q. Drawing straight lines from a-x/y to q and b-x/y to q it can be shown that the resulting triangle is equilateral in construction with all angles being 60°.
http://www.stonecarvingcourses.com/the-geometry-of-gothic-architecture
I've put together a small fiddle that does this. http://jsfiddle.net/7c7Vc/1/
If my understanding is correct that means (and since I am not a mathematician I'll describe this in laymans terms) that you need to draw two arcs with the compass centered on points x and y respectively, from the opposite point on the x to y line to the intersect point q, given the distance between points x and y as the radius width for your compass.
In the example I use the arc method to do this, here is a sample that will draw the right hand side arc of the arch...
ctx.arc(0, archHeight, archWidth, 0, 1.5*Math.PI + _30degrees, true);
Explanation
We center the compass on point x :
ctx.arc(0, archHeight, archWidth, 0, 1.5*Math.PI + _30degrees, true);
-------------
Set the radius of our circle to be the width of the arch (the distance between point x and point y)
ctx.arc(0, archHeight, archWidth, 0, 1.5*Math.PI + _30degrees, true);
---------
Start drawing from the direction of 3'oclock (which happens to be 0 radians)
ctx.arc(0, archHeight, archWidth, 0, 1.5*Math.PI + _30degrees, true);
--
Draw the arc until we hit point q, which in terms of the arc we are drawing is 30 degrees short of the direction of 12'oclock (using local variable _30degrees which holds the equivalent value in radians) and radians : 1.5*Math.PI for the direction 12'oclock.
ctx.arc(0, archHeight, archWidth, 0, 1.5*Math.PI + _30degrees, true);
------------------------
And we want to draw this arc counter-clockwise
ctx.arc(0, archHeight, archWidth, 0, 1.5*Math.PI + _30degrees, true);
----
The reverse method is used for the other arc making up the arch, take a look at the example for this
Notes on the code:
It uses some patterns to set up a factory that will create your arch based on either height or width, the returned arch knows how to draw itself on a canvas and has been given it's calculated height and width by the factory. If you prefer not to use this pattern you can extract the calculation bits out and simplify it.

Creating plane with triangular strips

I am trying to create a finely triangulated mesh. In the draw function :
// Draws triangular strip as only lines
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
// Create Cloth Mesh
glBegin(GL_TRIANGLE_STRIP);
glNormal3f(0,0,1);
for(float i = 0.0 ; i < 2.0; i+=.05)
{
for(float j = -1.0 ; j < 1.0 ; j+=.05)
{
glVertex3f(j,1-i+.05,0);
glVertex3f(j,1-i,0);
}
}
glEnd();
I get the following output :
which I what I expected.
But if I rotate the scene, I see this on the back side:
(If its not clear, its feebly lit mesh, but the triangles are not the same as showing up on front.)
Q1. Shouldn't the back side be not visible at all ? I have these flag enabled :
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
Q2. Even if the back side shows up, why does it shows these irregular, long triangles and not the same ones as on front ?
P.S. This is the resize function :
void MyGLWidget::resizeGL(int width, int height)
{
int side = qMin(width, height);
glViewport((width - side) / 2, (height - side) / 2, side, side);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2, +2, -2, +2, 1.0, 15.0);
glMatrixMode(GL_MODELVIEW);
}
P.P.S: Yes, I understand this is not modern OpenGL.
For me, this looks like the triangles, that are produced by the triangle-strip to "jump back" to the left side. This happens whenever you start a new row. Basically, they consist of the last-vertices of the previous row and the first vertices of the next row. Backface culling seems to work, but the large triangles are visible from the back because their winding order is exactly opposite to the one of the small triangles.
If you don't want to have them, you either have to reset the triangle-strip at the end of each row, or use another structure (GL_TRIANGLES).

Resources