private Curve DrawLineRamp(Curve road, Vector3d axis, int onStart, RampScale scale, double offset)
        {
            Point3d  start;
            Vector3d vx;
            Vector3d vy;

            if (axis == Vector3d.Unset)
            {
                axis = Vector3d.XAxis;
            }

            Vector3d axisPerp = new Vector3d(axis);

            axisPerp.Rotate(-Math.PI / 2, Vector3d.ZAxis);

            Vector3d roadv         = road.TangentAtStart;
            double   angleRoadAxis = Vector3d.VectorAngle(roadv, axis, Plane.WorldXY);

            if (angleRoadAxis < Math.PI * 0.25 || angleRoadAxis > Math.PI * 1.75 || (angleRoadAxis < Math.PI * 1.25 && angleRoadAxis > Math.PI * 0.75))
            {
                //selectperpvector
                vy = axisPerp;
            }
            else
            {
                //selectoriginvector
                vy = axis;
            }

            Point3d  testPoint = road.PointAtNormalizedLength(0.5);
            Vector3d dirInside = new Vector3d(roadv);

            dirInside.Rotate(-Math.PI / 2, Vector3d.ZAxis);

            Point3d testPointInside = testPoint + dirInside;
            Point3d testPointY      = testPoint + vy;

            Curve testLine = new LineCurve(testPointInside, testPointY);

            var testI = Rhino.Geometry.Intersect.Intersection.CurveCurve(testLine, road, 0, 0);

            if (testI.Count != 0)
            {
                vy.Reverse();
            }

            //true
            if (onStart == 0)
            {
                vx = new Vector3d(vy);
                vx.Rotate(Math.PI / 2, Vector3d.ZAxis);
                //vx = axis; // road.TangentAtStart;
                //if (vx == Vector3d.Unset)
                //    vx = road.TangentAtStart;
                //vy = new Vector3d(vx);
                //vy.Rotate(-Math.PI / 2, Vector3d.ZAxis);
                start = road.PointAtStart + road.TangentAtStart * (800 + offset);
                start = start + vy * 1000;
            }
            //false
            else
            {
                vx = new Vector3d(vy);
                vx.Rotate(-Math.PI / 2, Vector3d.ZAxis);
                //vx = -axis; //-road.TangentAtStart;
                //if (vx == -Vector3d.Unset)
                //    vx = -road.TangentAtStart;
                //vy = new Vector3d(vx);
                //vy.Rotate(Math.PI / 2, Vector3d.ZAxis);
                start = road.PointAtEnd + -road.TangentAtStart * (800 + offset);
                start = start + vy * 1000;
            }

            Point3d second = start + vx * UnderGroundParkingConsts.LinearRampWidth[(int)scale];
            Point3d third  = second + vy * (20000 + UnderGroundParkingConsts.WithinRadius[(int)scale]);
            Point3d forth  = third - vx * UnderGroundParkingConsts.LinearRampWidth[(int)scale];

            PolylineCurve plc = new PolylineCurve(new Point3d[] { start, second, third, forth, start });

            return(plc);
        }
        private Curve DrawCurvedRamp(Curve road, Vector3d axis, int onStart, RampScale scale, double beforeRamp, double offset)
        {
            Point3d  start;
            Vector3d vx;
            Vector3d vy;


            if (axis == Vector3d.Unset)
            {
                axis = Vector3d.XAxis;
            }

            double afterRamp = 10000 - beforeRamp;


            Vector3d axisPerp = new Vector3d(axis);

            axisPerp.Rotate(-Math.PI / 2, Vector3d.ZAxis);

            Vector3d roadv         = road.TangentAtStart;
            double   angleRoadAxis = Vector3d.VectorAngle(roadv, axis, Plane.WorldXY);

            if (angleRoadAxis < Math.PI * 0.25 || angleRoadAxis > Math.PI * 1.75 || (angleRoadAxis < Math.PI * 1.25 && angleRoadAxis > Math.PI * 0.75))
            {
                //selectperpvector
                vy = axisPerp;
            }
            else
            {
                //selectoriginvector
                vy = axis;
            }

            Point3d  testPoint = road.PointAtNormalizedLength(0.5);
            Vector3d dirInside = new Vector3d(roadv);

            dirInside.Rotate(-Math.PI / 2, Vector3d.ZAxis);

            Point3d testPointInside = testPoint + dirInside;
            Point3d testPointY      = testPoint + vy;

            Curve testLine = new LineCurve(testPointInside, testPointY);

            var testI = Rhino.Geometry.Intersect.Intersection.CurveCurve(testLine, road, 0, 0);

            if (testI.Count != 0)
            {
                vy.Reverse();
            }
            //true
            if (onStart == 0)
            {
                vx = new Vector3d(vy);
                vx.Rotate(Math.PI / 2, Vector3d.ZAxis);
                //vx = axis;//road.TangentAtStart;
                //if (vx == Vector3d.Unset)
                //    vx = road.TangentAtStart;
                //vy = new Vector3d(vx);
                //vy.Rotate(-Math.PI / 2, Vector3d.ZAxis);
                start = road.PointAtStart + vx * (800 + offset);
                start = start + vy * 1000;
            }
            //false
            else
            {
                vx = new Vector3d(vy);
                vx.Rotate(-Math.PI / 2, Vector3d.ZAxis);
                //vx = -axis;// - road.TangentAtStart;
                //if (vx == -Vector3d.Unset)
                //    vx = -road.TangentAtStart;
                //vy = new Vector3d(vx);
                //vy.Rotate(Math.PI / 2, Vector3d.ZAxis);
                start = road.PointAtEnd + vx * (800 + offset);
                start = start + vy * 1000;
            }

            Point3d second = start + vx * UnderGroundParkingConsts.CurveRampWidth[(int)scale];

            Point3d third     = second + vy * beforeRamp;//(20000 + UnderGroundParkingConsts.WithinRadius[(int)scale]);
            double  innerArcR = UnderGroundParkingConsts.WithinRadius[(int)scale];
            double  outerArcR = UnderGroundParkingConsts.WithinRadius[(int)scale] + UnderGroundParkingConsts.CurveRampWidth[(int)scale];
            Point3d forth     = third + vy * innerArcR + vx * innerArcR; // third - vx * UnderGroundParkingConsts.LinearRampWidth[(int)scale];
            Point3d fifth     = forth + vx * afterRamp;
            Point3d sixth     = fifth + vy * UnderGroundParkingConsts.CurveRampWidth[(int)scale];
            Point3d seventh   = sixth - vx * afterRamp;
            Point3d eighth    = seventh - vx * outerArcR - vy * outerArcR;
            Point3d ninth     = start;
            //polyline1
            PolylineCurve plc1 = new PolylineCurve(new Point3d[] { start, second, third });
            ArcCurve      arc1 = new ArcCurve(new Arc(third, vy, forth));
            PolylineCurve plc2 = new PolylineCurve(new Point3d[] { forth, fifth, sixth, seventh });
            ArcCurve      arc2 = new ArcCurve(new Arc(seventh, -vx, eighth));
            PolylineCurve plc3 = new PolylineCurve(new Point3d[] { eighth, ninth });

            Curve[] curvesToJoin = new Curve[] { plc1, arc1, plc2, arc2, plc3 };
            //Rhino.RhinoDoc.ActiveDoc.Objects.Add(Curve.JoinCurves(curvesToJoin)[0]);
            var joined = Curve.JoinCurves(curvesToJoin);

            if (joined.Length > 0)
            {
                return(joined[0]);
            }
            else
            {
                return(null);
            }

            //return plc;
        }
        public Curve DrawRamp(Plot plot, Vector3d lineAxis, List <Curve> obstacles)
        {
            //규모 판별 - 50 이상? 미만? 너비 3.3 or 6.5 , 내반경 5 or 6
            //innerboundary 기준 x (도로판별이힘듦)plot boundary 기준으로, '도로'에 '수직? 이어야 하나?' 인 '27m' 이상 길이 확보 가능? -> 직선 램프
            //불가능 -> 곡선램프 -> 시작 선, 도로 선, 장애물

            RampScale scale = RampScale.Under50;

            if (require > 50)
            {
                scale = RampScale.Over50;
            }

            //도로.
            Curve[]      boundaries = plot.Boundary.DuplicateSegments();
            List <Curve> roads      = new List <Curve>();

            for (int i = 0; i < boundaries.Length; i++)
            {
                if (plot.Surroundings[i] != 0)
                {
                    roads.Add(boundaries[i]);
                }
            }

            for (int i = 0; i < roads.Count; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    for (int l = 0; l < 100; l++)
                    {
                        double offsetTick = 100;//roads[i].GetLength() / 10;
                        if (l * offsetTick > roads[i].GetLength())
                        {
                            break;
                        }
                        Curve tempRamp = DrawLineRamp(roads[i], lineAxis, j, scale, l * offsetTick);
                        if (tempRamp == null)
                        {
                            continue;
                        }
                        bool collCheck             = CollisionCheck(tempRamp, obstacles);
                        RegionContainment isInside = Curve.PlanarClosedCurveRelationship(tempRamp, innerBoundary, Plane.WorldXY, 0);
                        if (collCheck && isInside == RegionContainment.AInsideB)
                        {
                            return(tempRamp);
                        }
                    }
                }
            }


            //for curvedramp
            for (int i = 0; i < roads.Count; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    for (int k = 0; k < 10; k++)
                    {
                        for (int l = 0; l < 100; l++)
                        {
                            double offsetTick = 100;//roads[i].GetLength() / 10;
                            if (l * offsetTick > roads[i].GetLength())
                            {
                                break;
                            }
                            double beforeRamp = 10000 - k * 1000;
                            Curve  tempRamp   = DrawCurvedRamp(roads[i], lineAxis, j, scale, beforeRamp, l * offsetTick);
                            if (tempRamp == null)
                            {
                                continue;
                            }
                            bool collCheck             = CollisionCheck(tempRamp, obstacles);
                            RegionContainment isInside = Curve.PlanarClosedCurveRelationship(tempRamp, innerBoundary, Plane.WorldXY, 0);
                            if (collCheck && isInside == RegionContainment.AInsideB)
                            {
                                return(tempRamp);
                            }
                        }
                    }
                }
            }

            //cant make ramp
            return(null);
        }