Example #1
0
            protected override float ComputePixel(ref InstanceContext ctx)
            {
                var sd = SignedDistance.Infinite.Distance;

                for (var i = 0; i < Shape.Count; ++i)
                {
                    var         minDistance = SignedDistance.Infinite;
                    EdgeSegment nearEdge    = null;
                    double      nearParam   = 0;
                    foreach (var edge in Shape[i])
                    {
                        double param    = 0;
                        var    distance = edge.SignedDistance(ctx.P, ref param);
                        if (distance < minDistance)
                        {
                            minDistance = distance;
                            nearEdge    = edge;
                            nearParam   = param;
                        }
                    }

                    if (Math.Abs(minDistance.Distance) < Math.Abs(sd))
                    {
                        sd          = minDistance.Distance;
                        ctx.Winding = -Windings[i];
                    }

                    nearEdge?.DistanceToPseudoDistance(ref minDistance, ctx.P, nearParam);
                    ContourSd[i] = new SingleDistance {
                        Dist = minDistance.Distance
                    };
                    ctx.UpdateDistance(Windings[i], minDistance.Distance);
                }

                return((float)(ComputeSd(Infinite, ref ctx).Dist / Range + 0.5));
            }
        public List <EdgeSegment> GetRawData(Room room,
                                             double DistanceToWall, double UnitWidth)
        {
            //Used to store the wall object.
            List <EdgeSegment> rSegments = new List <EdgeSegment>();

            #region The basics and datas
            const double er  = 0.0001;//used for error correction.
            Document     doc = room.Document;
            Autodesk.Revit.ApplicationServices.Application app = doc.Application;
            //get the level height of floor and ceiling
            //!!!!!current not consider different ceiling height or floor.Need improving.
            double levelC = room.ClosedShell.GetBoundingBox().Max.Z;
            double levelF = room.ClosedShell.GetBoundingBox().Min.Z;
            //Custom input data.
            double dist2W = DistanceToWall;
            double unitW  = UnitWidth;
            #endregion

            //get the boundary segments list
            IList <IList <BoundarySegment> > boundarys =
                room.GetBoundarySegments(new SpatialElementBoundaryOptions());

            //Loop through all the wall segment needed to oprate on
            //first layer is each boundary loop(in case a room has multiple boundaries)
            foreach (IList <BoundarySegment> groupSegments in boundarys)
            {
                //The stack is for the segments(one wall can be several segments)
                //The queue is for the wall after merging the segments.
                Stack <EdgeSegment> eSegments       = new Stack <EdgeSegment>();
                List <EdgeSegment>  eSegmentsMerged = new List <EdgeSegment>();

                //Second layer is the actual segment
                //in this loop process each segment opening info and log them
                foreach (BoundarySegment segment in groupSegments)
                {
                    #region Create the object,get the inner edge of a wall segment
                    EdgeSegment theSeg = new EdgeSegment();
                    Curve       segCrv = segment.GetCurve();
                    XYZ         start  = segCrv.GetEndPoint(0);
                    XYZ         end    = segCrv.GetEndPoint(1);
                    XYZ         normal;
                    theSeg.levelC = levelC;
                    theSeg.levelF = levelF;
                    theSeg.start  = new XYZ(start.X, start.Y, levelF);
                    theSeg.end    = new XYZ(end.X, end.Y, levelF);
                    #endregion

                    //The boundary segment may not be a wall
                    Element wallOrNot = doc.GetElement(segment.ElementId);

                    #region Seperate different category(Wall,Column or others)
                    Categories docCat   = doc.Settings.Categories;
                    ElementId  idColumn = docCat.get_Item(BuiltInCategory.OST_Columns).Id;
                    ElementId  idWall   = docCat.get_Item(BuiltInCategory.OST_Walls).Id;
                    //Case 1-A column or the end of a single wall.
                    if ((wallOrNot == null) || (wallOrNot.Category.Id.Equals(idColumn)))
                    {
                        //The room segments always search counterclockwise
                        //Thus compute the normal as follow
                        //Other data is not needed.Treat it as a full wall.
                        XYZ line = end - start;
                        normal        = new XYZ(-line.Y, line.X, 0);
                        theSeg.normal = normal / normal.GetLength();
                        eSegments.Push(theSeg);
                        continue;
                    }
                    //Case 2-Not column or wall.(Most likely curtain)Mark as noPanel.
                    if (!(wallOrNot.Category.Id.Equals(idWall)))
                    {
                        theSeg.NoPanel = true;
                        eSegments.Push(theSeg);
                        continue;
                    }
                    //Case 3-Walls
                    Wall theWall = wallOrNot as Wall;
                    #endregion

                    #region Get the sideface of a wall and get the profile curves
                    IList <Reference> sideFaces =
                        HostObjectUtils.GetSideFaces(theWall, ShellLayerType.Exterior);
                    //get the real face(why so long???)
                    Face face = doc.GetElement(sideFaces[0])
                                .GetGeometryObjectFromReference(sideFaces[0]) as Face;
                    //get edge loops as curveloops
                    IList <CurveLoop> openLoops = face.GetEdgesAsCurveLoops();
                    #endregion

                    //Some basic properties of the face.
                    normal = face.ComputeNormal(new UV(0, 0));
                    Plane plane = Plane.CreateByNormalAndOrigin(normal, start);

                    #region Check if curves are on the inner plane or not.
                    //(Might be on the other side of the wall)
                    //Log the correction vector in correction.
                    Curve checkCurve = openLoops[0].GetEnumerator().Current;
                    plane.Project(checkCurve.GetEndPoint(1), out UV uv, out double dist);
                    Transform correction = Transform.CreateTranslation(new XYZ(0, 0, 0));
                    if (dist > er) //Same wired reason.See "const double er" up front.
                    {
                        normal     = -normal;
                        correction = Transform.CreateTranslation(dist * normal);
                        plane      = Plane.CreateByNormalAndOrigin(normal, start);
                    }
                    #endregion

                    //Store all the endpoints and horizontal curves.
                    List <XYZ>   points = new List <XYZ>();
                    List <Curve> hoCrvs = new List <Curve>();
                    foreach (CurveLoop curveloop in openLoops)
                    {
                        foreach (Curve curve in curveloop)
                        {
                            points.Add(correction.OfPoint(curve.GetEndPoint(0)));
                            //If curve is horizontal,and in the middle range,log it
                            double cSz = curve.GetEndPoint(0).Z;
                            double cEz = curve.GetEndPoint(1).Z;
                            if ((Math.Abs(cSz - cEz) < er) && (cSz > levelF + er) && (cSz < levelC - er))
                            {
                                hoCrvs.Add(curve.CreateTransformed(correction));
                            }
                        }
                    }

                    #region Sort pts according to curve direction
                    var tempPts = from point in points
                                  where ((point.Z > levelF + er) && (point.Z < levelC - er))
                                  select new XYZ(point.X, point.Y, levelF);
                    List <XYZ> relayPts = tempPts.ToList <XYZ>();
                    relayPts.Add(start); relayPts.Add(end);
                    var sortPt = from point in relayPts
                                 where (segCrv.Distance(point) < er)
                                 orderby(point - start).GetLength()
                                 select point;
                    List <XYZ> sortPtList = sortPt
                                            .Distinct(new PtEqualComparer())
                                            .ToList <XYZ>();
                    if (!(sortPtList[0] == start))
                    {
                        sortPtList.Reverse();
                    }
                    sortPtList.RemoveAt(sortPtList.Count - 1);
                    sortPtList.RemoveAt(0);
                    #endregion

                    #region log the data
                    theSeg.crvList = hoCrvs;
                    theSeg.ptList  = sortPtList;
                    theSeg.normal  = normal;
                    #endregion

                    //Find insert element(and project on plane)
                    List <ElementId> insertIds = theWall
                                                 .FindInserts(true, true, true, true).Distinct().ToList();
                    foreach (ElementId eId in insertIds)
                    {
                        Element        currentRoom = doc.GetElement(eId);
                        BoundingBoxXYZ box         = currentRoom.get_Geometry(new Options()).GetBoundingBox();
                        XYZ            ept         = 0.5 * (box.Max + box.Min);
                        XYZ            v           = ept - plane.Origin;
                        double         signedDist  = plane.Normal.DotProduct(v);
                        XYZ            eptnew      = ept - signedDist * normal;
                        theSeg.insertPts.Add(eptnew);
                    }

                    //Push to the stack.
                    eSegments.Push(theSeg);
                }

                #region Merge from segments to walls...
                //Merge the segments that are on same curve.
                int         segNum = eSegments.Count;
                EdgeSegment sNew;
                for (int i = 1; i < segNum; i++)
                {
                    EdgeSegment s1 = eSegments.Pop();
                    EdgeSegment s2 = eSegments.Pop();
                    if (!(s2.MergeWith(s1, out sNew)))
                    {
                        eSegmentsMerged.Add(s1);
                    }
                    eSegments.Push(sNew);
                }

                //Compare the final one to the first one again
                EdgeSegment sf1 = eSegmentsMerged[0];
                EdgeSegment sf2 = eSegments.Pop();
                if (sf2.MergeWith(sf1, out sNew))
                {
                    eSegmentsMerged.RemoveAt(0);
                }
                eSegmentsMerged.Add(sNew);
                //Because the use of stack,the order need to be reversed back.
                eSegmentsMerged.Reverse();
                #endregion

                #region Set the offset for each corner according to dist2W
                int wallNum = eSegmentsMerged.Count;
                eSegmentsMerged.Add(eSegmentsMerged[0]);
                for (int i = 0; i < wallNum; i++)
                {
                    EdgeSegment SegCur = eSegmentsMerged[i];
                    EdgeSegment SegAft = eSegmentsMerged[i + 1];
                    double      angle  = SegCur.unitV.AngleOnPlaneTo(SegAft.unitV, XYZ.BasisZ);
                    SegCur.end   -= Math.Tan(0.5 * angle) * dist2W * SegCur.unitV;
                    SegAft.start += Math.Tan(0.5 * angle) *
                                    (dist2W + UnitUtils.ConvertToInternalUnits(10, DisplayUnitType.DUT_MILLIMETERS)) *
                                    SegAft.unitV;
                }
                eSegmentsMerged.RemoveAt(eSegmentsMerged.Count - 1);
                #endregion

                rSegments.AddRange(eSegmentsMerged);
            }

            return(rSegments);
        }
Example #3
0
 public EdgeHolder(EdgeSegment segment)
 {
     this.edgeSegment = segment;
 }