예제 #1
0
        /// <summary>
        /// 두 라인의 교차를 확인한다.
        /// 단, 한 선의 점이 다른 선위에 올라가거나, 다른 선의 점과 겹치는 것은 고려하지 않는다.
        /// </summary>
        public bool isIntersected(CLine firstLine, CLine secondLine)
        {
            double dFL_P1_X = roundDigitOfShape(firstLine.m_startPoint.X);
            double dFL_P1_Y = roundDigitOfShape(firstLine.m_startPoint.Y);

            double dFL_P2_X = roundDigitOfShape(firstLine.m_endPoint.X);
            double dFL_P2_Y = roundDigitOfShape(firstLine.m_endPoint.Y);

            double dSL_P1_X = roundDigitOfShape(secondLine.m_startPoint.X);
            double dSL_P1_Y = roundDigitOfShape(secondLine.m_startPoint.Y);

            double dSL_P2_X = roundDigitOfShape(secondLine.m_endPoint.X);
            double dSL_P2_Y = roundDigitOfShape(secondLine.m_endPoint.Y);

            /// 알고리즘 2 번
            ///
            /// ">" 를 ">=" 로 변경한 것은 꼭지점끼리 만나는 경우는 교차로 취급하지 않기 위해서이다.
            if (((dFL_P1_X - dFL_P2_X) * (dSL_P1_Y - dFL_P1_Y) + (dFL_P1_Y - dFL_P2_Y) * (dFL_P1_X - dSL_P1_X)) *
                ((dFL_P1_X - dFL_P2_X) * (dSL_P2_Y - dFL_P1_Y) + (dFL_P1_Y - dFL_P2_Y) * (dFL_P1_X - dSL_P2_X)) >= 0.0)
            {
                return(false);
            }

            if (((dSL_P1_X - dSL_P2_X) * (dFL_P1_Y - dSL_P1_Y) + (dSL_P1_Y - dSL_P2_Y) * (dSL_P1_X - dFL_P1_X)) *
                ((dSL_P1_X - dSL_P2_X) * (dFL_P2_Y - dSL_P1_Y) + (dSL_P1_Y - dSL_P2_Y) * (dSL_P1_X - dFL_P2_X)) >= 0.0)
            {
                return(false);
            }

            return(true);
        }
예제 #2
0
        /// <summary>
        /// 두 라인의 접촉을 확인한다.
        ///
        /// 하나의 선에 다른 선의 두점 중 한점이라도 올라탔는지를 확인해서 접촉을 판단한다.
        /// </summary>
        public bool isContacted(CLine firstLine, CLine secondLine)
        {
            // 첫번째 라인에 두번째 라인의 양점이 올라갔는지를 판단한다.
            if (true == isPerchedOnLine(firstLine, secondLine.m_startPoint))
            {
                return(true);
            }

            if (true == isPerchedOnLine(firstLine, secondLine.m_endPoint))
            {
                return(true);
            }

            // 두번째 라인에 첫번째 라인의 양점이 올라갔는지를 판단한다.
            if (true == isPerchedOnLine(secondLine, firstLine.m_startPoint))
            {
                return(true);
            }

            if (true == isPerchedOnLine(secondLine, firstLine.m_endPoint))
            {
                return(true);
            }

            return(false);
        }
예제 #3
0
        /// <summary>
        /// 두 라인의 겹침을 확인한다.
        ///
        /// 두선이 같은 직선위에 있는지를 판단하여 겹침을 검사한다.
        /// 단, 같은 직선위에 있더라도 떨어져 있는 직선일 수 있기 때문에 양점의 X 좌표를 비교해서 겹치는 구간이 있는지 판단한다.        ///
        /// </summary>
        public bool isOverlaped(CLine firstLine, CLine secondLine)
        {
            double dFL_P1_X = firstLine.m_startPoint.X;
            double dFL_P1_Y = firstLine.m_startPoint.Y;

            double dFL_P2_X = firstLine.m_endPoint.X;
            double dFL_P2_Y = firstLine.m_endPoint.Y;

            double dSL_P1_X = secondLine.m_startPoint.X;
            double dSL_P1_Y = secondLine.m_startPoint.Y;

            double dSL_P2_X = secondLine.m_endPoint.X;
            double dSL_P2_Y = secondLine.m_endPoint.Y;

            /// 첫번째 라인의 직선방정식 기울기와 Y 절편을 계산한다.
            double dA = (dFL_P2_Y - dFL_P1_Y) / (dFL_P2_X - dFL_P1_X);
            double dB = dFL_P1_Y - dA * (dFL_P1_X);

            /// 첫번째 라인의 직선방정식에 두번째 라인 두점의 X 값을 입력하여 Y 값을 계산한다.
            double dStartY = dA * dSL_P1_X + dB;
            double dEndY   = dA * dSL_P2_X + dB;

            double dBigX   = Math.Max(dFL_P1_X, dFL_P2_X);
            double dSmallX = Math.Min(dFL_P1_X, dFL_P2_X);

            // 계산된 Y 값과 실제 두번째 라인 두점의 값이 일치하면
            // 하나의 직선 방정식 위에 두개의 라인이 존재한다고 판단할 수 있다.
            if (isEqual(dStartY, dSL_P1_Y) && isEqual(dEndY, dSL_P2_Y))
            {
                // 하나의 직선 방정식 위에 두개의 라인이 존재하더라도 두 라인이 떨어져 있을 수 있다.
                // 하나의 직선 방정식 위에 존재하면서 두개의 라인이 겹치는지를 아래의 조건을 판단하고 있다.
                // ( 방법은 두번째 라인의 두점의 X 값이 첫번째 라인의 X 값들 사이에 있는지로 검사하고 있다.)
                if (roundDigitOfShape(dBigX) >= roundDigitOfShape(dSL_P1_X) && roundDigitOfShape(dSmallX) <= roundDigitOfShape(dSL_P1_X) || roundDigitOfShape(dBigX) >= roundDigitOfShape(dSL_P2_X) && roundDigitOfShape(dSmallX) <= roundDigitOfShape(dSL_P2_X))
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                return(false);
            }
        }
예제 #4
0
        /// <summary>
        /// 선 위에 다른 점이 올라가 있는 지를 검사한다.
        /// </summary>
        public bool isPerchedOnLine(CLine line, CPoint point)
        {
            double dL_P1_X = line.m_startPoint.X;
            double dL_P1_Y = line.m_startPoint.Y;

            double dL_P2_X = line.m_endPoint.X;
            double dL_P2_Y = line.m_endPoint.Y;

            double dP_X = point.X;
            double dP_Y = point.Y;

            /// 라인의 X 구간
            double dBigX   = Math.Max(dL_P1_X, dL_P2_X);
            double dSmallX = Math.Min(dL_P1_X, dL_P2_X);

            /// 라인의 Y 구간
            double dBigY   = Math.Max(dL_P1_Y, dL_P2_Y);
            double dSmallY = Math.Min(dL_P1_Y, dL_P2_Y);

            /// 직선이 수직선인 경우는 예외 처리한다.
            if (isEqual(dL_P2_X, dL_P1_X))
            {
                /// 점의 X 좌표가 직선의 X 좌표와 일치하면 라인 위의 점이다.
                if (isEqual(dL_P1_X, dP_X))
                {
                    if (roundDigitOfShape(dBigY) >= roundDigitOfShape(dP_Y) && roundDigitOfShape(dSmallY) <= roundDigitOfShape(dP_Y))
                    {
                        return(true);
                    }
                }
            }
            /// 직선이 수평선인 경우는 예외 처리한다.
            else if (isEqual(dL_P2_Y, dL_P1_Y))
            {
                /// 점의 Y 좌표가 직선의 Y 좌표와 일치하면 라인 위의 점이다.
                if (isEqual(dL_P1_Y, dP_Y))
                {
                    if (roundDigitOfShape(dBigX) >= roundDigitOfShape(dP_X) && roundDigitOfShape(dSmallX) <= roundDigitOfShape(dP_X))
                    {
                        return(true);
                    }
                }
            }
            else
            {
                /// 라인의 직선방정식 기울기와 Y 절편을 계산한다.
                double dL_A = (dL_P2_Y - dL_P1_Y) / (dL_P2_X - dL_P1_X);
                double dL_B = dL_P1_Y - dL_A * (dL_P1_X);

                /// 라인의 직선방정식에 점의 X 값을 입력하여 Y 값을 계산한다.
                double dP_Calc_Y = dL_A * dP_X + dL_B;

                /// 계산된 Y 값과 좌표 Y 값이 일치하면 직선의 방정식위에 있는 점이다.
                if (isEqual(dP_Calc_Y, dP_Y))
                {
                    /// 직선의 방정식 위에 있는 점 중에서 실제 라인 위에 있는 점인지를 판단한다.
                    if ((roundDigitOfShape(dBigX) >= roundDigitOfShape(dP_X) && roundDigitOfShape(dSmallX) <= roundDigitOfShape(dP_X)) && (roundDigitOfShape(dBigY) >= roundDigitOfShape(dP_Y) && roundDigitOfShape(dSmallY) <= roundDigitOfShape(dP_Y)))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
예제 #5
0
        /// <summary>
        /// 재귀호출을 사용해서 FACE 내부점을 찾아낸다.
        /// 재질 블럭점을 찾는 것이기 때문에 절대좌표를 사용해야 한다.
        ///
        /// 참고 사이트 : http://bowbowbow.tistory.com/24
        /// </summary>
        /// <param name="minX">내부점을 찾는 구간의 X 점 최소값</param>
        /// <param name="maxX">내부점을 찾는 구간의 X 점 최대값</param>
        /// <param name="baseY">내부 좌표값을 찾은 Y 위치 </param>
        /// <returns></returns>
        public CPoint findInsidePoint(CFace face, double minX, double maxX, double minY, double maxY)
        {
            int nRightIntersection = 0;
            int nLeftIntersection  = 0;

            int nRightPerchedPointOnCheckLine = 0;
            int nLeftPerchedPointOnCheckLine  = 0;

            int nPerchedCenterPointOnFaceLine = 0;

            CLine rightCheckLine = new CLine();
            CLine leftCheckLine  = new CLine();

            CPoint centerPoint = new CPoint();

            double baseY   = (minY + maxY) / 2.0f;
            double centerX = (minX + maxX) / 2.0f;

            //// 너무 작은 소수점 이하는 정리한다.
            minX  = roundDigitOfShape(minX);
            maxX  = roundDigitOfShape(maxX);
            baseY = roundDigitOfShape(baseY);

            // 중심점을 만든다.
            centerPoint.X = centerX;
            centerPoint.Y = baseY;

            /// create a right check line
            rightCheckLine.m_startPoint.X = centerX;
            rightCheckLine.m_startPoint.Y = baseY;
            rightCheckLine.m_endPoint.X   = maxX + 10.0f;  // 오른 검색선의 끝을 maxX 보다 10 크게 한다.
            rightCheckLine.m_endPoint.Y   = baseY;

            /// create a left check line
            leftCheckLine.m_startPoint.X = centerX;
            leftCheckLine.m_startPoint.Y = baseY;
            leftCheckLine.m_endPoint.X   = minX - 10.0f;  // 오른 검색선의 끝을 minX 보다 10 작게 한다.
            leftCheckLine.m_endPoint.Y   = baseY;

            /// 매번 생성하는 Property 이기 때문에
            /// LineList 는 새로운 List에  담는 동작 한번만 호출하고, 사용은 새로운 List 를 사용한다.
            List <CLine> listAbsoluteLine = new List <CLine>();

            listAbsoluteLine = face.AbsoluteLineList;

            foreach (CLine line in listAbsoluteLine)
            {
                /// Face 선들과 검색 선의 교차 횟수 확인
                if (true == isIntersected(line, rightCheckLine))
                {
                    nRightIntersection++;
                }

                if (true == isIntersected(line, leftCheckLine))
                {
                    nLeftIntersection++;
                }

                /// Face 선의 양점이 검색 선 위에 올라가 있는지 확인
                if (true == isPerchedOnLine(rightCheckLine, line.m_startPoint))
                {
                    nRightPerchedPointOnCheckLine++;
                }

                if (true == isPerchedOnLine(rightCheckLine, line.m_endPoint))
                {
                    nRightPerchedPointOnCheckLine++;
                }

                if (true == isPerchedOnLine(leftCheckLine, line.m_startPoint))
                {
                    nLeftPerchedPointOnCheckLine++;
                }

                if (true == isPerchedOnLine(leftCheckLine, line.m_endPoint))
                {
                    nLeftPerchedPointOnCheckLine++;
                }

                /// Face 선위에 중심점이 올라가 있는지 확인
                if (true == isPerchedOnLine(line, centerPoint))
                {
                    nPerchedCenterPointOnFaceLine++;
                }
            }


            //-------------------------------------------------------------------
            // 내부점 판단
            //
            // 내부점을 만족하면 Point 를 리턴하고,
            // 만족하지 못하면 측정 면적을 수정하고 재귀호출을 통해 Point 를 찾아낸다.
            //------------------------------------------------------------------
            //
            CPoint point = new CPoint();

            // Center 점이 Face Line 위에 올라가 있으면 우측 1/2 사각형에서 내부점을 찾는다.
            if (nPerchedCenterPointOnFaceLine > 0)
            {
                return(findInsidePoint(face, centerX, maxX, minY, maxY));
            }

            // Face Line 의 양점이 우측 검색 라인에 올라가는 경우는 상측 1/2 사각형에서 내부점을 찾는다.
            if (nRightPerchedPointOnCheckLine > 0 || nLeftPerchedPointOnCheckLine > 0)
            {
                return(findInsidePoint(face, minX, maxX, baseY, maxY));
            }

            // 양측이 홀수이면 Inside Point 이다.
            if (EMNumberKind.ODD == getNumberKind(nRightIntersection) && EMNumberKind.ODD == getNumberKind(nLeftIntersection))
            {
                point.X = centerX;
                point.Y = baseY;

                return(point);
            }
            /// 왼쪽이 짝수이면 X 값의 최소값과 중심값 사이의 중점을 다시 확인한다.
            else if (EMNumberKind.EVEN == getNumberKind(nLeftIntersection))
            {
                return(findInsidePoint(face, minX, centerX, minY, maxY));
            }
            /// 오른쪽이 짝수이면 X 값의 중심값과 최대값 사이의 중점을 다시 확인한다.
            else if (EMNumberKind.EVEN == getNumberKind(nRightIntersection))
            {
                return(findInsidePoint(face, centerX, maxX, minY, maxY));
            }
            else
            {
                /// Block Point 를 찾기 위해서 findInsidePoint() 를 호출할 때
                /// Face 형상의 문제로 오류가 발생하여 Face 바깥의 지점으로 계산이 리턴되면
                /// Block Point 가 추가되지 못해서
                /// FEMM 에서 Block Point 에 재질 인가 할 때 다른 Block Point 에 인가되는 문제가 발생한다.
                ///
                /// 따라서 findInsidePoint() 에서 내부점을 찾지 못할 때는
                /// 중심의 좌표값을 넘기지 않고 null 을 리턴하여 Block Point 재질 설정 동작을 막는다.
                CNotice.noticeWarningID("FTCT");
                return(null);
            }
        }
예제 #6
0
        /// <summary>
        /// 재귀호출을 사용해서 FACE 내부점을 찾아낸다.
        /// 재질 블럭점을 찾는 것이기 때문에 절대좌표를 사용해야 한다.
        ///
        /// 참고 사이트 : http://bowbowbow.tistory.com/24
        /// </summary>
        /// <param name="minX">내부점을 찾는 구간의 X 점 최소값</param>
        /// <param name="maxX">내부점을 찾는 구간의 X 점 최대값</param>
        /// <param name="baseY">내부 좌표값을 찾은 Y 위치 </param>
        /// <returns></returns>
        public CPoint findInsidePoint(CFace face, double minX, double maxX, double baseY)
        {
            int nRightIntersection = 0;
            int nLeftIntersection  = 0;

            int nRightPerchedPoint = 0;
            int nLeftPerchedPoint  = 0;

            // 자리수 정리
            minX  = round(minX);
            maxX  = round(maxX);
            baseY = round(baseY);

            double centerX = (minX + maxX) / 2.0f;

            CLine rightLine = new CLine();
            CLine leftLine  = new CLine();

            /// create a right check line
            rightLine.m_startPoint.m_dX = centerX;
            rightLine.m_startPoint.m_dY = baseY;
            rightLine.m_endPoint.m_dX   = maxX + 10.0f;  // 오른 검색선의 끝을 maxX 보다 10 크게 한다.
            rightLine.m_endPoint.m_dY   = baseY;

            /// create a left check line
            leftLine.m_startPoint.m_dX = centerX;
            leftLine.m_startPoint.m_dY = baseY;
            leftLine.m_endPoint.m_dX   = minX - 10.0f;  // 오른 검색선의 끝을 minX 보다 10 작게 한다.
            leftLine.m_endPoint.m_dY   = baseY;

            /// 매번 생성하는 Property 이기 때문에
            /// LineList 는 새로운 List에  담는 동작 한번만 호출하고, 사용은 새로운 List 를 사용한다.
            List <CLine> listAbsoluteLine = new List <CLine>();

            listAbsoluteLine = face.AbsoluteLineList;

            /// Face 의 선과 검색선의 교차점을 찾는다.
            foreach (CLine line in listAbsoluteLine)
            {
                if (true == isIntersected(line, rightLine))
                {
                    nRightIntersection++;
                }

                if (true == isIntersected(line, leftLine))
                {
                    nLeftIntersection++;
                }
            }

            /// 교차를 검사할때 Face 선의 양점은 고려하지 않는다.
            /// 따라서 검색선에 Face 선의 점을 지나치는 경우는 교차점이 인식되지 못한다.
            /// 라인의 양점이 검색선에 올가가는지도 추가로 검색한다.
            ///
            foreach (CLine line in listAbsoluteLine)
            {
                // 만약 시작과 끝이 같이 올라간 경우라면 검색선에 Face 선이 올라간 경우로 검색에서 제외한다.
                // 라인의 한점만 올라간 경우를 Perched Point 로 사용한다.
                if (true == isPerchedOnLine(rightLine, line.m_startPoint) && true == isPerchedOnLine(rightLine, line.m_endPoint))
                {
                    nRightPerchedPoint += 0;
                }
                else if (true == isPerchedOnLine(rightLine, line.m_startPoint))
                {
                    nRightPerchedPoint++;
                }
                else if (true == isPerchedOnLine(rightLine, line.m_endPoint))
                {
                    nRightPerchedPoint++;
                }

                if (true == isPerchedOnLine(leftLine, line.m_startPoint) && true == isPerchedOnLine(leftLine, line.m_endPoint))
                {
                    nLeftPerchedPoint += 0;
                }
                else if (true == isPerchedOnLine(leftLine, line.m_startPoint))
                {
                    nLeftPerchedPoint++;
                }
                else if (true == isPerchedOnLine(leftLine, line.m_endPoint))
                {
                    nLeftPerchedPoint++;
                }
            }

            if ((nRightPerchedPoint % 2 != 0) || (nLeftPerchedPoint % 2 != 0))
            {
                CNotice.printTrace("findInsidePoint 에서 PerchedPoint 값이 홀수가 되었습니다.");
            }

            /// 점이 올라가는 경우 두점이 같이 올라가기 때문에 한번 교차에 두번 카운팅이 된다.
            /// 따라서 1/2 로 처리한다.
            ///
            nRightIntersection += (int)(nRightPerchedPoint / 2.0f);
            nLeftIntersection  += (int)(nLeftPerchedPoint / 2.0f);

            CPoint point = new CPoint();

            /// 양측이 홀수이면 Inside Point 이다.
            if (EMNumberKind.ODD == getNumberKind(nRightIntersection) && EMNumberKind.ODD == getNumberKind(nLeftIntersection))
            {
                point.m_dX = centerX;
                point.m_dY = baseY;

                return(point);
            }
            /// 왼쪽이 짝수이면 X 값의 최소값과 중심값 사이의 중점을 다시 확인한다.
            else if (EMNumberKind.EVEN == getNumberKind(nLeftIntersection))
            {
                return(findInsidePoint(face, minX, centerX, baseY));
            }
            /// 오른쪽이 짝수이면 X 값의 중심값과 최대값 사이의 중점을 다시 확인한다.
            else if (EMNumberKind.EVEN == getNumberKind(nRightIntersection))
            {
                return(findInsidePoint(face, centerX, maxX, baseY));
            }
            else
            {
                /// Block Point 를 찾기 위해서 findInsidePoint() 를 호출할 때
                /// Face 형상의 문제로 오류가 발생하여 Face 바깥의 지점으로 계산이 리턴되면
                /// Block Point 가 추가되지 못해서
                /// FEMM 에서 Block Point 에 재질 인가 할 때 다른 Block Point 에 인가되는 문제가 발생한다.
                ///
                /// 따라서 findInsidePoint() 에서 내부점을 찾지 못할 때는
                /// 중심의 좌표값을 넘기지 않고 null 을 리턴하여 Block Point 재질 설정 동작을 막는다.
                CNotice.noticeWarningID("FTCT");
                return(null);
            }
        }