AOJ本の読書メモ   AOJ    次のAOJの問題へ    前のAOJの問題へ

CGL_1_B: Reflection


問題へのリンク


C#のソース

using System;
using System.Collections.Generic;
using System.Linq;

// Q060 直線 p1p2 に対する点 pの反射 https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_B&lang=jp
class Program
{
    static string InputPattern = "InputX";

    static List<string> GetInputList()
    {
        var WillReturn = new List<string>();

        if (InputPattern == "Input1") {
            WillReturn.Add("0 0 3 4");
            WillReturn.Add("3");
            WillReturn.Add("2 5");
            WillReturn.Add("1 4");
            WillReturn.Add("0 3");
            //4.2400000000 3.3200000000
            //3.5600000000 2.0800000000
            //2.8800000000 0.8400000000
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("0 0 2 0");
            WillReturn.Add("3");
            WillReturn.Add("-1 1");
            WillReturn.Add("0 1");
            WillReturn.Add("1 1");
            //-1.0000000000 -1.0000000000
            //0.0000000000 -1.0000000000
            //1.0000000000 -1.0000000000
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    static decimal mP1X;
    static decimal mP1Y;
    static decimal mP2X;
    static decimal mP2Y;

    static void Main()
    {
        List<string> InputList = GetInputList();

        decimal[] wkArr = { };
        Action<string> SplitAct = pStr =>
            wkArr = pStr.Split(' ').Select(X => decimal.Parse(X)).ToArray();

        SplitAct(InputList[0]);
        mP1X = wkArr[0];
        mP1Y = wkArr[1];
        mP2X = wkArr[2];
        mP2Y = wkArr[3];

        foreach (string EachStr in InputList.Skip(2)) {
            SplitAct(EachStr);
            decimal PX = wkArr[0];
            decimal PY = wkArr[1];
            Solve(PX, PY);
        }
    }

    static void Solve(decimal pPX, decimal pPY)
    {
        // 処理01 内積からCosを求める
        decimal Vector1_X = pPX - mP1X;
        decimal Vector1_Y = pPY - mP1Y;
        decimal Vector2_X = mP2X - mP1X;
        decimal Vector2_Y = mP2Y - mP1Y;

        decimal Naiseki = Vector1_X * Vector2_X + Vector1_Y * Vector2_Y;

        Func<decimal, decimal, decimal> DeriveVectorABS = (pX, pY) =>
        {
            double X_double = (double)pX;
            double Y_double = (double)pY;
            return (decimal)Math.Sqrt(X_double * X_double + Y_double * Y_double);
        };

        decimal Vector1_ABS = DeriveVectorABS(Vector1_X, Vector1_Y);
        decimal Vector2_ABS = DeriveVectorABS(Vector2_X, Vector2_Y);

        decimal CosVal;
        if (Naiseki == 0M) { // 零ベクトルの場合があるので、0割りを防止しておく
            CosVal = 0M;
        }
        else {
            CosVal = Naiseki / Vector1_ABS / Vector2_ABS;
        }

        // 処理02 P1 -> P2 と P1 -> Mid の比で、中点の座標を求める
        decimal Distance_P1_Mid = Vector1_ABS * CosVal;

        decimal Mid_X = mP1X + Vector2_X * Distance_P1_Mid / Vector2_ABS;
        decimal Mid_Y = mP1Y + Vector2_Y * Distance_P1_Mid / Vector2_ABS;

        // 処理03 中点なので (P1 + X) / 2 = Mid
        // ∴ X = 2*Mid - P1

        decimal Answer_X = 2 * Mid_X - pPX;
        decimal Answer_Y = 2 * Mid_Y - pPY;

        Console.WriteLine("{0} {1}", Answer_X, Answer_Y);
    }
}


解説

射影の座標を中点として、反射の座標を求めてます。