線対称、点対称の図形

 投稿者:山中和義  投稿日:2015年 5月18日(月)10時23分17秒
  問題 点つなぎパズル
与えられた座標を順につないでできる図形が
・線対称なのか
・点対称なのか
を出力するプログラムを作成してください。


考察
線対称
 2点(選び方はC(n,2)通り)を結ぶ線分の垂直二等分線を対称軸として、
 各点を線対称変換させて、重複することなく元の点に重なる。
点対称
 各点を重心を中心に180°回転させて、重複することなく元の点に重なる。
(終り)



SET WINDOW -1,6,-1,6
DRAW grid

!DATA 4 !点の個数
!DATA 1,5, 1,3, 4,0, 4,2 !座標(x,y) 点対称
DATA 4
DATA 0,0, 0,2, 2,2, 2,0 !線対称、点対称
!DATA 5
!DATA 0,2, 1,0, 3,0, 4,2, 2,3 !線対称
!DATA 6
!DATA 0,0, 3,0, 3,1, 5,3, 2,3, 2,2 !点対称
!DATA 6
!DATA 0,1, 1,0, 4,0, 2,1, 3,2, 2,3 !error

!DATA 19 !花
!DATA 3,0, 2,1, 0,1, 1,0, 5,0, 6,1, 4,1, 3,0, 3,3, 4,3
!DATA 5,4, 5,6, 4,5, 3,6, 2,5, 1,6, 1,4, 2,3, 3,3

READ N
DIM X(N),Y(N)
FOR i=1 TO N !点の座標を読み込む
   READ X(i),Y(i)
   PLOT TEXT ,AT X(i)+0.1,Y(i)+0.1: STR$(i)
   DRAW disk WITH SCALE(0.1)*SHIFT(X(i),Y(i))
NEXT i
FOR i=1 TO N !点をつなぐ
   PLOT LINES: X(i),Y(i);
NEXT i
PLOT LINES: X(1),Y(1) !一筆書き


!線対称

FOR P=1 TO N-1 !対称軸となる2点
   FOR Q=P+1 TO N
      CALL gcP2LINE(X(P),Y(P),X(Q),Y(Q), A,B,C) !垂直二等分線
      SET AREA COLOR 2
      FOR i=1 TO N
         CALL gcSYMMETRY2(A,B,C,X(i),Y(i), XX,YY) !線対称
         FOR K=1 TO N !重なるかどうか確認する
            IF ABS(XX-X(K))<1E-10 AND ABS(YY-Y(K))<1E-10 THEN EXIT FOR
         NEXT K
         IF K>N THEN EXIT FOR !重ならない

         !!PLOT TEXT ,AT XX+0.1,YY-0.1: STR$(i)
         DRAW disk WITH SCALE(0.1)*SHIFT(XX,YY)
      NEXT i
      IF i>N THEN !すべての点が重なるなら
         SET LINE COLOR 4
         CALL gcDRAWLINE(A,B,C)
         PRINT "線対称な図形です。"; P;Q
      END IF
   NEXT Q
NEXT P


!点対称

LET GX=0 !重心を求める
LET GY=0
FOR i=1 TO N
   LET GX=GX+X(i)
   LET GY=GY+Y(i)
NEXT i
LET GX=GX/N
LET GY=GY/N
SET AREA COLOR 4
PLOT TEXT ,AT GX+0.1,GY+0.1: "G"
DRAW disk WITH SCALE(0.1)*SHIFT(GX,GY)

SET AREA COLOR 2
FOR i=1 TO N !重心で180°回転する
   CALL gcSYMMETRY(X(i),Y(i),GX,GY, XX,YY)

   FOR K=1 TO N !重なるかどうか確認する
      IF ABS(XX-X(K))<1E-10 AND ABS(YY-Y(K))<1E-10 THEN EXIT FOR
   NEXT K
   IF K>N THEN EXIT FOR !重ならない

   PLOT TEXT ,AT XX+0.1,YY-0.1: STR$(i)
   DRAW disk WITH SCALE(0.1)*SHIFT(XX,YY)
NEXT i
IF i>N THEN PRINT "点対称な図形です。"

END


!FV.LIB 抜粋

EXTERNAL SUB gcDRAWLINE(L,M,N) !直線Lx+My+N=0を描く
IF (L=0 AND M=0) THEN
   PRINT "L=M=0なので、直線が成立しません。"; L;M;N
ELSE
   ASK WINDOW x1,x2,y1,y2
   IF ABS(L)>ABS(M) THEN !y=±xの傾きより大きいなら ※y軸に平行な直線を含む
      PLOT LINES: -(M*y1+N)/L,y1; -(M*y2+N)/L,y2
   ELSE
      PLOT LINES: x1,-(L*x1+N)/M; x2,-(L*x2+N)/M
   END IF
END IF
END SUB

!点A(x1,y1), B(x2,y2)を結ぶ線分ABの垂直二等分線
! 線分ABの中点を通り、線分ABの傾きに垂直な直線 Y-(y1+y2)/2=-(x2-x1)/(y2-y1)(X-(x1+x2)/2) より
EXTERNAL SUB gcP2LINE(x1,y1,x2,y2, L,M,N)
IF (x1=x2 AND y1=y2) THEN
   PRINT "2点は同一点なので、線分が成立しません。"; x1;y1;x2;y2
ELSE
   LET L=x2-x1
   LET M=y2-y1
   LET N=-(L*(x1+x2)+M*(y1+y2))/2
END IF
END SUB

EXTERNAL SUB gcSYMMETRY(X,Y,PX,PY, QX,QY) !点Aに対する点対称の点
LET QX=2*PX-X !点(X,Y)と対称点(QX,QY)の中点が点(PX,PY)なので、PX=(X+QX)/2
LET QY=2*PY-Y
END SUB

!線対称(Lx+My+N=0)の点
! 点A(x1,y1)、対称点A'(x2,y2)とする。
! 点A,A'の中点は直線上の点なので、L((x1+x2)/2)+M((y1+y2)/2)+N=0 ∴Lx2+My2=-(Lx1+My1+2N) ←式1
! また、直線AA'と直線とは直交するので、傾き((y2-y1)/(x2-x1))(-L/M)=-1 ∴Mx2-Ly2=Mx1-Ly1 ←式2
! L*式1+M*式2より、(L^2+M^2)x2=-L(Lx1+My1+2N) +M(Mx1-Ly1)=(L^2+M^2)x1-2L(Lx1+My1+N)
! M*式1-L*式2より、(L^2+M^2)y2=-M(Lx1+My1+2N) -L(Mx1-Ly1)=(L^2+M^2)y1-2M(Lx1+My1+N)
EXTERNAL SUB gcSYMMETRY2(L,M,N,PX,PY, QX,QY) !線対称(Lx+My+N=0)の点
LET m3=L*L+M*M
IF m3=0 THEN
   PRINT "L=M=0なので、直線が成立しません。"; L;M;N
ELSE
   LET t=(L*PX+M*PY+N)/m3
   LET QX=PX-2*L*t
   LET QY=PY-2*M*t
END IF
END SUB



 

戻る