Reputation: 32481
I have some delegates and a method:
delegate Point Translate(Point p);
delegate Translate Transform(Translate t);
Translate forward = p => new Point(p.X + 1, p.Y);
Question: How can I implement a method like this:
Transform Rotate90 = ??
So that Rotate90
rotates any Translate
function 90 clockwise. So:
Point startPoint = new Point(1, 1);
Point endPoint = (Rotate90(forward))(startPoint);
//desired output: Point(1, 0)
EDIT 1:
I'm not going to apply Translate
functions one by one on a point. What I need is to apply some transformed functions (Translate
function that have been rotated or reflexed) on a point.
WHAT I NEED: How can I write a Rotate90
which if I pass it (p=>new Point(p.X+1, p.y))
it returns me a function with the same effect as (p=>new Point(p.X, p.Y-1))
.
EDIT 2: Some examples:
Translate forward = p => new Point(p.X + 1, p.Y);
Translate backward = p => new Point(p.X - 1, p.Y);
Translate downward = p => new Point(p.X, p.Y - 1);
Translate runningForward = p => new Point(p.X + 5, p.Y);
Transform Rotate90Cw = ??
Point samplePoint = new Point(1, 1);
Point p1 = (Rotate90Cw(forward))(samplePoint); //must be (1,0)
Point p2 = (Rotate90Cw(backward))(samplePoint); //must be (1,2)
Point p3 = (Rotate90Cw(downward))(samplePoint); //must be (0,1)
Point p4 = (Rotate90Cw(runningForward))(samplePoint); //must be (1,-4)
Point p4 = (Rotate90Cw(Rotate90Cw(forward)))(samplePoint); //must be (0,1)
I need a single
Rotate90Cw
function that can be applied on anyTranslate
function and returns a properTranslate
function. So the effect of applyingRotate90Cw(forward)
on a point would be the same as applyingdownward
on a point. And so on...
I'm not going to make a separate Rotate
function for every case (e.g. forwardRotated, downwardRotated and ...
Upvotes: 1
Views: 153
Reputation: 32481
I solve it this way (EDITED):
Translate Rotate90Cw(Translate moveFunction)
{
return Rotate(moveFunction, Math.PI / 2.0);
}
Translate Rotate(Translate moveFunction, double angle)
{
Point tempPoint = moveFunction(new Point(0, 0));
double sin = Math.Sin(angle);
double cos = Math.Cos(angle);
return p => new Point(p.X + tempPoint.X * cos + tempPoint.Y * sin,
p.Y - tempPoint.X * sin + tempPoint.Y * cos);
}
Check if it is working:
Rotate90Cw(Rotate90Cw(runningForward))(new Point(1, 1)); //output: (-4,0.9999999)
Rotate90Cw(runningForward)(new Point(1, 1)); //output: (1,-4)
Rotate90Cw(backward)(new Point(1, 1)); //output: (1,2)
Rotate90Cw(downward)(new Point(1, 1)); //output: (0,1)
Upvotes: 0
Reputation: 1500525
It's not clear that you actually want two delegates. It seems that really you want one delegate representing an arbitrary transformation from Point
to Point
- and you can then compose transformations. For example:
delegate Point Transform(Point input);
private static Transform Compose(Transform first, Transform second)
{
return p => second(first(p));
}
Transform forward = p => new Point(p.X + 1, p.Y);
Transform rotate90 = p => new Point(p.Y, -p.X);
Transform forwardThenRotate = Compose(forward, rotate);
EDIT: It looks like what you actually want is a transform (taking in a transform) along the lines of:
We can do that easily:
Transform forward = p => new Point(p.X + 1, p.Y);
Transform rotate90 = p => new Point(-p.Y, p.X);
Point forwardRotatedPoint = rotate90(forward(new Point(0, 0));
Transform forwardRotated = p => new Point(forwardRotatedPoint.X + p.X,
forwardRotatedPoint.Y + p.Y);
As I said elsewhere though, you probably actually want a Vector
type, which has X
and Y
components... then you could have several composable concepts:
Upvotes: 3