1

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 any Translate function and returns a proper Translate function. So the effect of applying Rotate90Cw(forward) on a point would be the same as applying downward on a point. And so on...

I'm not going to make a separate Rotate function for every case (e.g. forwardRotated, downwardRotated and ...

1
  • What about using extension methods imbrication the same way LINQ is designed ? Commented Mar 28, 2013 at 15:07

2 Answers 2

3

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:

  • Apply the original transform to (0, 0)
  • Rotate the result
  • Translate the incoming point by that much

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:

  • Creating a transformation (point to point) from a vector
  • Rotating one vector to create another
  • Composing transformations
Sign up to request clarification or add additional context in comments.

8 Comments

Defining Rotate that accepts a point and returns another point do not make sense. It is expected for Rotate to get a vector, and here the Translate delegate is the most similar things to vector.
@HosseinNarimaniRad: I disagree completely - it's a rotation around the origin. I think it makes much more sense as a function on points and a function on arbitrary transformations. (If you really meant your Translate to be just a fixed translation, that should be using a vector-like type, not a delegate.)
You are correct in this case. But I'm not going to apply some map functions on a point one by one. I want to apply some transformed map functions on a point.
@HosseinNarimaniRad: I'm afraid you haven't made your requirements clear. I've provided one example of how you can compose transformations though - I'd hope that would be sufficient. If not, you really need to clarify your question.
I edited my post. By the way the output of your Compose is a Point not a Transform (as you write it).
|
0

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)

1 Comment

Right, that's basically the same approach as I used, just accepting an angle (although still oddly with 90 in the name) - but I still think you should have a different type for Translate. A translation isn't an arbitrary point to point transformation: it's the addition of a vector. So it would be better to represent it as a vector to start with.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.