Exemple #1
0
        public override Brep GetBoundingBrep(double offset = 0.0)
        {
            //Curve CL = Centreline.Extend(CurveEnd.Both, offset, CurveExtensionStyle.Line);
            Curve  CL     = Centreline;
            double Length = CL.GetLength();
            double hW     = Data.NumWidth * Data.LamWidth / 2 + offset;
            double hH     = Data.NumHeight * Data.LamHeight / 2 + offset;

            double[] DivParams = new double[] { CL.Domain.Min, CL.Domain.Max };

            GenerateCorners(offset);

            Curve[][] LoftCurves = new Curve[4][];

            for (int i = 0; i < 4; ++i)
            {
                LoftCurves[i] = new Curve[2];
            }

            Rhino.Geometry.Transform xform;
            Line l1 = new Line(m_section_corners[0], m_section_corners[1]);
            Line l2 = new Line(m_section_corners[1], m_section_corners[2]);
            Line l3 = new Line(m_section_corners[2], m_section_corners[3]);
            Line l4 = new Line(m_section_corners[3], m_section_corners[0]);
            Line temp;

            for (int i = 0; i < DivParams.Length; ++i)
            {
                Plane p = GetPlane(DivParams[i]);
                xform            = Rhino.Geometry.Transform.PlaneToPlane(Plane.WorldXY, p);
                temp             = l1; temp.Transform(xform);
                LoftCurves[0][i] = temp.ToNurbsCurve();
                temp             = l2; temp.Transform(xform);
                LoftCurves[1][i] = temp.ToNurbsCurve();
                temp             = l3; temp.Transform(xform);
                LoftCurves[2][i] = temp.ToNurbsCurve();
                temp             = l4; temp.Transform(xform);
                LoftCurves[3][i] = temp.ToNurbsCurve();
            }

            Brep brep = new Brep();

            for (int i = 0; i < 4; ++i)
            {
                Brep[] loft = Brep.CreateFromLoft(LoftCurves[i], Point3d.Unset, Point3d.Unset, LoftType.Normal, false);
                if (loft == null || loft.Length < 1)
                {
                    continue;
                }
                for (int j = 0; j < loft.Length; ++j)
                {
                    brep.Append(loft[j]);
                }
            }

            brep.JoinNakedEdges(Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance);
            brep = brep.CapPlanarHoles(Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance);

            return(brep);
        }
Exemple #2
0
        public static Brep FtBoundingBox(Curve ftCurve, Double height, Double tol)
        {
            Vector3d heightVector = new Vector3d(0, 0, height);
            Brep     extrusion    = Extrude(ftCurve, heightVector, tol);
            Brep     boudingBox   = extrusion.CapPlanarHoles(tol);

            return(boudingBox);
        }
Exemple #3
0
        public Brep BuildSolid(List <Brep> brepFaces, Brep ftPlanar, double height, double tolerance)
        {
            Brep roofBrep      = Brep.JoinBreps(brepFaces, tolerance)[0];
            Brep downExtrusion = GetExtrusion(roofBrep, new Vector3d(0, 0, -1.5 * height), tolerance);

            roofBrep.Join(downExtrusion, tolerance, false);
            roofBrep = TrimExtrusion(ftPlanar, roofBrep, tolerance);

            Brep solid = roofBrep.CapPlanarHoles(tolerance);

            return(solid);
        }
Exemple #4
0
        private Brep ExtrudeCurveBothSide(Curve Crv, Vector3d Direction, bool BothSide, bool IsCape)
        {
            double Tolerance = Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance;

            if (Direction.Length == 0)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "拉伸向量的长度不能为0");
                return(null);
            }
            if (BothSide)
            {
                Crv.Transform(Transform.Translation(Direction));
                Direction.Reverse();
                Direction = Direction * 2;
            }
            if (Crv.IsPlanar())
            {
                try
                {
                    Brep Temp = Extrusion.CreateExtrusion(Crv, Direction).ToBrep();
                    if (IsCape)
                    {
                        return(Temp.CapPlanarHoles(Tolerance));
                    }
                    else
                    {
                        return(Temp);
                    }
                }
                catch (Exception e)
                {
                    this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, string.Format("内部错误:{0}", e.Message));
                    return(null);
                }
            }
            else
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "输入的几何体不符合条件");
                return(null);
            }
        }
        private Brep trimOutMillingVolume()
        {
            var  result     = innerBoundary.Trim(frontPlane, Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance);
            Brep millingVol = new Brep();

            if (result.Length > 0)
            {
                millingVol = result[0];
                //flip the back plane
                Plane trim = new Plane(backPlane.Origin, backPlane.Normal);
                trim.Flip();
                var result2 = millingVol.Trim(trim, Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance);
                if (result2.Length > 0)
                {
                    millingVol = result2[0];
                }
            }
            Brep capped = millingVol.CapPlanarHoles(Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance);

            return(capped);
        }
        private GH_Brep CreateSlabBrep(double depth, IList <PolylineCurve> curveList, IEnumerable <Point3d> topPts)
        {
            if (depth > 0)
            {
                Vector3d normal = Vector3d.CrossProduct(curveList[0].TangentAtEnd, curveList[0].TangentAtStart);
                curveList[1] = new PolylineCurve(topPts.Select(pt => pt - normal * depth));
                Brep loftBrep  = Brep.CreateFromLoft(curveList, Point3d.Unset, Point3d.Unset, LoftType.Straight, false)[0];
                Brep capedBrep = loftBrep.CapPlanarHoles(_tolerance[0]);

                if (capedBrep == null)
                {
                    return(NonPlanarBrep(depth, curveList));
                }
                CheckBrepOrientation(capedBrep);

                return(new GH_Brep(capedBrep));
            }

            return(new GH_Brep(curveList[0].IsPlanar()
                     ? Brep.CreatePlanarBreps(curveList[0], _tolerance[0])[0]
                     : Brep.CreatePatch(new[] { curveList[0] }, 5, 5, _tolerance[0])));
        }
Exemple #7
0
        public static List <Brep> DrawHouse(Household hhp)
        {
            double   height  = Consts.FloorHeight;
            Curve    outline = hhp.GetOutline();
            Polyline outPoly = CurveTools.ToPolyline(outline);

            Brep x = Extrusion.Create(outline, height, true).ToBrep();

            x.CapPlanarHoles(1);

            double windowSide   = 300;
            double windowLow    = 300;
            double windowHeight = 2100;
            double windowDepth  = 200;

            List <Brep> wins = new List <Brep>();

            for (int i = 0; i < hhp.LightingEdge.Count; i++)
            {
                //Rhino.RhinoDoc.ActiveDoc.Objects.Add(hhp.LightingEdge[i].ToNurbsCurve());
                //var c = hhp.LightingEdge[i].ToNurbsCurve().Trim(CurveEnd.Both, 300);
                //var p1 = c.PointAtStart + Vector3d.ZAxis * 300;
                //var p2 = c.PointAtStart + Vector3d.ZAxis * 2400;
                //var p3 = c.PointAtEnd + Vector3d.ZAxis * 2400;
                //var p4 = c.PointAtEnd + Vector3d.ZAxis * 300;
                //Brep[] open = Brep.CreatePlanarBreps(new PolylineCurve(new Point3d[] { p1, p2, p3, p4, p1 }));
                Line tempLine = hhp.LightingEdge[i];

                Point3d  midPoint  = tempLine.PointAt(0.5);
                Vector3d windowVec = tempLine.UnitTangent;
                windowVec.Rotate(Math.PI / 2, Vector3d.ZAxis);
                midPoint.Transform(Transform.Translation(Vector3d.Multiply(windowVec, 10)));

                if (hhp.GetOutline().Contains(midPoint) == Rhino.Geometry.PointContainment.Inside)
                {
                    tempLine.Flip();
                }

                tempLine.Extend(-windowSide, -windowSide);

                Curve tempCurve = tempLine.ToNurbsCurve();
                tempCurve.Translate(Vector3d.Multiply(Vector3d.ZAxis, windowLow));
                Point3d pt1 = tempCurve.PointAtStart;
                Point3d pt2 = tempCurve.PointAtEnd;
                Point3d pt3 = tempCurve.PointAtEnd;
                pt3.Transform(Transform.Translation(Vector3d.Multiply(Vector3d.ZAxis, windowHeight)));
                Point3d pt4 = tempCurve.PointAtStart;
                pt4.Transform(Transform.Translation(Vector3d.Multiply(Vector3d.ZAxis, windowHeight)));
                Point3d        pt5          = tempCurve.PointAtStart;
                List <Point3d> windowPoints = new List <Point3d>();
                windowPoints.Add(pt1);
                windowPoints.Add(pt2);
                windowPoints.Add(pt3);
                windowPoints.Add(pt4);
                windowPoints.Add(pt5);
                Polyline windowPolyline = new Polyline(windowPoints);
                Curve    win            = windowPolyline.ToNurbsCurve();


                Plane windowPlane;
                win.TryGetPlane(out windowPlane);
                Vector3d windowNormal = windowPlane.Normal;
                Curve    windowCurve  = win.Duplicate() as Curve;
                windowCurve.Translate(Vector3d.Multiply(windowNormal, windowDepth));
                Surface windowSurface = Surface.CreateExtrusion(windowCurve, Vector3d.Multiply(windowNormal, -windowDepth * 2));
                Brep    windowBrep    = windowSurface.ToBrep();
                Brep[]  withHolesTemp = x.Split(windowBrep, 1);

                if (withHolesTemp.Length != 0)
                {
                    x = withHolesTemp[0];
                }

                Curve duplicatedWindowCurve = (win.Duplicate() as Curve);
                duplicatedWindowCurve.Transform(Transform.Translation(windowNormal * (windowDepth - 100)));

                Curve windowCurveBottom = duplicatedWindowCurve.DuplicateSegments()[0];
                Curve heightCurve       = duplicatedWindowCurve.DuplicateSegments()[1];

                wins.AddRange(DrawWindowAll(windowCurveBottom, heightCurve.GetLength(), false));

                Curve[] tempLoftBase = { win, duplicatedWindowCurve };

                Curve pathCurve = new LineCurve(Point3d.Origin, new Point3d(windowNormal * (-windowDepth + 100)));
                wins.Add(Brep.JoinBreps(Brep.CreateFromLoft(tempLoftBase, Point3d.Unset, Point3d.Unset, LoftType.Normal, false), 0)[0]);
            }


            //1. 양쪽에서 300씩 , 위400 아래300 사각형.빵꾸. 안쪽으로 200
            //->창틀
            //2. 사방 30씩, 안쪽으로 100
            //->창문와꾸
            //3. 창 안쪽에서 20, 창문와꾸 30, 바깥쪽50 ,길이 1200 * 2
            //4. ㅊ



            //Brep w1 = Brep.create  hhp.LightingEdge[0]
            wins.Add(x);
            return(wins);
        }
        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            double tolerance      = doc.ModelAbsoluteTolerance;
            double angleTolerance = doc.ModelAngleToleranceRadians;


            List <Curve> icur = new List <Curve>();

            GetObject gcr = new Rhino.Input.Custom.GetObject();

            gcr.SetCommandPrompt("Select reference circles for prongs. (No curves)");
            gcr.GeometryFilter              = Rhino.DocObjects.ObjectType.Curve;
            gcr.GroupSelect                 = true;
            gcr.SubObjectSelect             = true;
            gcr.DeselectAllBeforePostSelect = true;
            gcr.OneByOnePostSelect          = false;
            gcr.GetMultiple(1, 0);

            for (int ie = 0; ie < gcr.ObjectCount; ie++)
            {
                Rhino.DocObjects.ObjRef      objref = gcr.Object(ie);
                Rhino.DocObjects.RhinoObject obj    = objref.Object();
                if (obj == null)
                {
                    return(Result.Failure);
                }
                Curve refcr = objref.Curve();
                if (refcr == null)
                {
                    return(Result.Failure);
                }
                obj.Select(false);

                icur.Add(refcr);
            }

            while (true)
            {
                m_escape_key_pressed       = false;
                RhinoApp.EscapeKeyPressed += RhinoApp_EscapeKeyPressed;

                Point3d pt0 = new Point3d(0, 0, hight);
                Point3d pt1 = new Point3d(0, 0, -(length - hight));

                double rotationRadiant = ((rotation / 180) * 3.1415);

                List <Point3d> curvePoints = new List <Point3d>()
                {
                    pt0, pt1
                };
                Curve prongCurve = Curve.CreateInterpolatedCurve(curvePoints, 3);

                if (!capBool)
                {
                    capMode = PipeCapMode.Flat;
                }
                else if (capBool)
                {
                    capMode = PipeCapMode.Round;
                }

                Brep[] cylBrep1 = Brep.CreatePipe(prongCurve, prongDia / 2, false, capMode, false, tolerance, angleTolerance);
                Brep   cylBrep2 = cylBrep1[0];
                cylBrep2.Faces.RemoveAt(2);
                Brep cylBrep3 = cylBrep2.CapPlanarHoles(tolerance);

                if (capBool)
                {
                    Vector3d     scaleVec   = new Vector3d(0, 0, 1);
                    var          scalePlane = new Plane(pt0, scaleVec);
                    var          capScale   = Transform.Scale(scalePlane, 1.0, 1.0, capHight);
                    var          surf2      = cylBrep3.Faces[1].UnderlyingSurface();
                    NurbsSurface nurbSurf2  = surf2.ToNurbsSurface();
                    nurbSurf2.Transform(capScale);
                    Brep capBrep = nurbSurf2.ToBrep();
                    cylBrep3.Append(capBrep);
                    cylBrep3.Faces.RemoveAt(1);
                }

                cylBrep3.Compact();
                cylBrep3.JoinNakedEdges(tolerance);
                string instDefCount = DateTime.Now.ToString("ddMMyyyyHHmmss");
                Brep[] brepArray    = new Brep[1] {
                    cylBrep3
                };
                var prongIndex = doc.InstanceDefinitions.Add("Prong" + instDefCount, "RefProng", Point3d.Origin, brepArray);

                foreach (Curve c in icur)
                {
                    Circle circleProngs = new Circle();
                    c.TryGetCircle(out circleProngs, tolerance);
                    NurbsCurve curveProngs = circleProngs.ToNurbsCurve();

                    Plane    planeNew = circleProngs.Plane;
                    Vector3d plVec    = planeNew.Normal;

                    if (planeNew == null)
                    {
                        curveProngs.DivideByCount(3, true, out Point3d[] curveProngsPoints);
                        planeNew = new Plane(curvePoints[0], curveProngsPoints[1], curveProngsPoints[2]);
                    }


                    Curve[] offsetCurveArray = curveProngs.Offset(planeNew, prongDia / 4, tolerance, CurveOffsetCornerStyle.Sharp);

                    Curve offsetCurve = offsetCurveArray[0];

                    double[] segParameters = offsetCurve.DivideByCount(prongCount, true);

                    List <Point3d> prongPoints = new List <Point3d>();
                    List <Guid>    idsInter    = new List <Guid>();

                    foreach (double p in segParameters)
                    {
                        Point3d zen        = new Point3d(0, 0, 0);
                        Point3d prongPoint = offsetCurve.PointAt(p);

                        Point3d  center  = circleProngs.Center;
                        Vector3d moveV   = new Vector3d(prongPoint);
                        Vector3d zaxis   = new Vector3d(0.0, 0.0, 1.0);
                        Plane    planeOr = new Plane(zen, zaxis);
                        Plane    plane   = new Plane(prongPoint, plVec);

                        var transform1 = Transform.PlaneToPlane(planeOr, plane);
                        var transform2 = Transform.Rotation(rotationRadiant, plVec, center);

                        var prongA = doc.Objects.AddInstanceObject(prongIndex, transform1);
                        var prongB = doc.Objects.Transform(prongA, transform2, true);

                        ids.Add(prongB);
                    }
                    doc.Views.Redraw();
                }


                GetOption go = new Rhino.Input.Custom.GetOption();
                go.SetCommandPrompt("Set prong parameters.");
                go.AcceptNothing(true);

                var countProng  = new Rhino.Input.Custom.OptionInteger(prongCount);
                var diaProng    = new Rhino.Input.Custom.OptionDouble(prongDia);
                var hightProng  = new Rhino.Input.Custom.OptionDouble(hight);
                var lengthProng = new Rhino.Input.Custom.OptionDouble(length);
                var rotProng    = new Rhino.Input.Custom.OptionDouble(rotation);
                var capProng    = new Rhino.Input.Custom.OptionToggle(capBool, "Flat", "Round");
                var hightCap    = new Rhino.Input.Custom.OptionDouble(capHight);

                go.AddOptionInteger("Count", ref countProng);
                go.AddOptionDouble("Diameter", ref diaProng);
                go.AddOptionDouble("Hight", ref hightProng);
                go.AddOptionDouble("Length", ref lengthProng);
                go.AddOptionDouble("Rotation", ref rotProng);
                go.AddOptionToggle("Cap", ref capProng);
                if (capBool)
                {
                    go.AddOptionDouble("Caphight", ref hightCap);
                }

                GetResult res = go.Get();

                if (m_escape_key_pressed)
                {
                    break;
                }

                hight      = hightProng.CurrentValue;
                length     = lengthProng.CurrentValue;
                prongCount = countProng.CurrentValue;
                prongDia   = diaProng.CurrentValue;
                rotation   = rotProng.CurrentValue;
                capBool    = capProng.CurrentValue;
                capHight   = hightCap.CurrentValue;

                if (length <= 0.0)
                {
                    length = 1.0;
                }
                if (prongCount <= 0)
                {
                    prongCount = 1;
                }
                if (prongDia <= 0.0)
                {
                    prongDia = 1.0;
                }
                if (res == GetResult.Nothing)
                {
                    break;
                }

                doc.Objects.Delete(ids, true);
            }
            RhinoApp.EscapeKeyPressed -= RhinoApp_EscapeKeyPressed;

            doc.Groups.Add(ids);

            return(Result.Success);
        }
Exemple #9
0
        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            double tolerance = doc.ModelAbsoluteTolerance;

            List <Curve> icur = new List <Curve>();

            GetObject gcr = new Rhino.Input.Custom.GetObject();

            gcr.SetCommandPrompt("Select reference circles for drill. (No curves)");
            gcr.GeometryFilter              = Rhino.DocObjects.ObjectType.Curve;
            gcr.GroupSelect                 = true;
            gcr.SubObjectSelect             = true;
            gcr.DeselectAllBeforePostSelect = true;
            gcr.OneByOnePostSelect          = false;
            gcr.GetMultiple(1, 0);

            for (int ie = 0; ie < gcr.ObjectCount; ie++)
            {
                Rhino.DocObjects.ObjRef      objref = gcr.Object(ie);
                Rhino.DocObjects.RhinoObject obj    = objref.Object();
                if (obj == null)
                {
                    return(Result.Failure);
                }
                Curve refcr = objref.Curve();
                if (refcr == null)
                {
                    return(Result.Failure);
                }
                obj.Select(false);

                icur.Add(refcr);
            }

            while (true)
            {
                m_escape_key_pressed       = false;
                RhinoApp.EscapeKeyPressed += RhinoApp_EscapeKeyPressed;


                List <Curve> curveDrill = new List <Curve>();

                Point3d centerTop = new Point3d(0, 0, (headDrill + topDrill) * drillScale);
                Circle  circleTop = new Circle(centerTop, ancheadDrill / 2 * drillScale);
                Curve   curveTop  = circleTop.ToNurbsCurve();
                curveDrill.Add(curveTop);
                Point3d centerMid = new Point3d(0, 0, topDrill * drillScale);
                Circle  circleMid = new Circle(centerMid, drillScale / 2);
                Curve   curveMid  = circleMid.ToNurbsCurve();
                curveDrill.Add(curveMid);
                Circle circleBase = new Circle(drillScale / 2);
                Curve  curveBase  = circleBase.ToNurbsCurve();
                curveDrill.Add(curveBase);
                Point3d centerLow = new Point3d(0, 0, -midDrill * drillScale);
                Circle  circleLow = new Circle(centerLow, ancDrill / 2 * drillScale);
                Curve   curveLow  = circleLow.ToNurbsCurve();
                curveDrill.Add(curveLow);
                if (bottDrill != 0)
                {
                    Point3d centerBot = new Point3d(0, 0, (-midDrill - bottDrill) * drillScale);
                    Circle  circleBot = new Circle(centerBot, ancDrill / 2 * drillScale);
                    Curve   curveBot  = circleBot.ToNurbsCurve();
                    curveDrill.Add(curveBot);
                }


                Brep[] cylBrep1     = Brep.CreateFromLoft(curveDrill, Point3d.Unset, Point3d.Unset, LoftType.Straight, false);
                Brep[] cylBrep2     = Brep.CreateBooleanUnion(cylBrep1, tolerance);
                Brep   cylBrepFinal = cylBrep1[0];
                cylBrepFinal = cylBrepFinal.CapPlanarHoles(tolerance);


                string instDefCount = DateTime.Now.ToString("ddMMyyyyHHmmss");
                Brep[] brepArray    = new Brep[1] {
                    cylBrepFinal
                };
                var drillIndex = doc.InstanceDefinitions.Add("Drill" + instDefCount, "RefDrill 1mm", Point3d.Origin, brepArray);

                foreach (Curve c in icur)
                {
                    Circle circleDrill = new Circle();
                    c.TryGetCircle(out circleDrill, tolerance);

                    double   radiusDrill = circleDrill.Diameter;
                    Point3d  center      = circleDrill.Center;
                    Vector3d moveV       = new Vector3d(center);
                    Vector3d zaxis       = new Vector3d(0.0, 0.0, 1.0);
                    Plane    planeOr     = new Plane(center, zaxis);
                    Plane    planeNew    = circleDrill.Plane;
                    var      transform1  = Transform.Translation(moveV);
                    var      transform2  = Transform.Scale(center, radiusDrill);
                    var      transform3  = Transform.PlaneToPlane(planeOr, planeNew);

                    var stoneA = doc.Objects.AddInstanceObject(drillIndex, transform1);
                    var stoneB = doc.Objects.Transform(stoneA, transform2, true);
                    var stoneC = doc.Objects.Transform(stoneB, transform3, true);

                    ids.Add(stoneC);

                    doc.Views.Redraw();
                }


                GetOption go = new Rhino.Input.Custom.GetOption();
                go.SetCommandPrompt("Set drill parameters.");
                go.AcceptNothing(true);

                var drillHead    = new Rhino.Input.Custom.OptionDouble(headDrill);
                var drillAncHead = new Rhino.Input.Custom.OptionDouble(ancheadDrill);
                var drillTop     = new Rhino.Input.Custom.OptionDouble(topDrill);
                var drillMid     = new Rhino.Input.Custom.OptionDouble(midDrill);
                var drillAnc     = new Rhino.Input.Custom.OptionDouble(ancDrill);
                var drillBott    = new Rhino.Input.Custom.OptionDouble(bottDrill);
                var scaleDrill   = new Rhino.Input.Custom.OptionDouble(drillScale);
                go.AddOptionDouble("Top", ref drillHead);
                go.AddOptionDouble("TopAngle", ref drillAncHead);
                go.AddOptionDouble("Mid", ref drillTop);
                go.AddOptionDouble("Bottom", ref drillMid);
                go.AddOptionDouble("BottomAngle", ref drillAnc);
                go.AddOptionDouble("Tail", ref drillBott);
                go.AddOptionDouble("Scale", ref scaleDrill);


                GetResult res = go.Get();

                if (m_escape_key_pressed)
                {
                    break;
                }



                topDrill     = drillTop.CurrentValue;
                midDrill     = drillMid.CurrentValue;
                ancDrill     = drillAnc.CurrentValue;
                bottDrill    = drillBott.CurrentValue;
                drillScale   = scaleDrill.CurrentValue;
                headDrill    = drillHead.CurrentValue;
                ancheadDrill = drillAncHead.CurrentValue;


                if (res == GetResult.Nothing)
                {
                    break;
                }

                doc.Objects.Delete(ids, true);
            }
            RhinoApp.EscapeKeyPressed -= RhinoApp_EscapeKeyPressed;

            doc.Groups.Add(ids);

            return(Result.Success);
        }