简体   繁体   中英

Functions with other functions as input using delegates in C#

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, py)) it returns me a function with the same effect as (p=>new Point(pX, pY-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 (eg forwardRotated, downwardRotated and ...

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

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM