Beispiel #1
0
        /// <summary>
        /// Computes the intersection of one or more line strings.
        /// </summary>
        public void Compute()
        {
            this.intersections = new List <Coordinate>();
            this.edgeIndexes   = new List <Tuple <Int32, Int32> >();
            Event currentEvent = this.eventQueue.Next();

            while (currentEvent != null)
            {
                EndPointEvent endPointEvent = currentEvent as EndPointEvent;

                if (endPointEvent != null)
                {
                    this.ProcessEndPointEvent(endPointEvent);
                }

                IntersectionEvent intersectionEvent = currentEvent as IntersectionEvent;

                if (intersectionEvent != null)
                {
                    // intersection point event: switch the two concerned segments and check for possible intersection with their below and above segments
                    this.ProcessIntersectionEvent(intersectionEvent);
                }

                currentEvent = this.eventQueue.Next();
            }

            this.hasResult = true;
        }
        private void ProcessIntersectionEvent(Plan plan, IntersectionEvent intersectionEvent)
        {
            foreach (var chain in intersectionEvent.chains)
            {
                SimplifyChain(plan, chain);
            }
            intersectionEvent.chains.RemoveAll(c => c.Count == 0);

            if (intersectionEvent.chains.Count >= 2)
            {
                for (var i = 0; i < intersectionEvent.chains.Count; i++)
                {
                    var chain         = intersectionEvent.chains[i];
                    var previousChain = intersectionEvent.chains.GetLooped(i - 1);
                    var vertex        = chain[0];
                    plan.Remove(vertex);
                    skeleton.AddVertex(vertex);

                    var newVertex = new Plan.Vertex(intersectionEvent.position)
                    {
                        previousPolygonIndex = vertex.previousPolygonIndex,
                        nextPolygonIndex     = previousChain[0].nextPolygonIndex
                    };
                    plan.Insert(newVertex, vertex.previous, previousChain[0].next);
                    CalculateBisector(newVertex);
                }
            }
        }
Beispiel #3
0
 public FryIntersection(IntersectionEvent intEvent, KeyValuePair <Guid, Curve> curveAData, KeyValuePair <Guid, Curve> curveBData)
 {
     this.pA        = intEvent.PointA;
     this.pB        = intEvent.PointB;
     this.CurveA_Id = curveAData.Key;
     this.CurveB_Id = curveBData.Key;
     this.tA        = intEvent.ParameterA;
     this.tB        = intEvent.ParameterB;
     // Get tangent vectors from curves
     vecA = curveAData.Value.TangentAt(intEvent.ParameterA);
     vecB = curveBData.Value.TangentAt(intEvent.ParameterB);
 }
        private IntersectionEvent FindIntersectionEvent(Plan.Vertex searchVertex)
        {
            var vertex = searchVertex;

            do
            {
                if (!vertex.inEvent && vertex != searchVertex && IncidentalVertices(searchVertex, vertex))
                {
                    var intersectionEvent = new IntersectionEvent(searchVertex.position);
                    ExpandEvent(intersectionEvent, searchVertex);
                    return(intersectionEvent);
                }
                vertex = vertex.next;
            } while (vertex != searchVertex);
            return(null);
        }
Beispiel #5
0
        internal void addToFlippedEdgeInfo(int flippedEdgeIndex, Face face, IntersectionEvent intersection)
        {
            Boolean isNew = true;

            for (int k = 0; k < flippedEdgeInfo.Count; k++)
            {
                if (flippedEdgeInfo[k].edge.index == face.faceEdges[flippedEdgeIndex].index)
                {
                    flippedEdgeInfo[k].addSecondInfo(face, intersection.PointA);
                    isNew = false;
                }
            }
            if (isNew)
            {
                flippedEdgeInfo.Add(new FlippedEdge(face.faceEdges[flippedEdgeIndex], face, intersection.PointA));
            }
        }
        private void ExpandEvent(IntersectionEvent intersectionEvent, Plan.Vertex startVertex)
        {
            var vertex = startVertex;

            do
            {
                if (!vertex.inEvent && IncidentalVertices(intersectionEvent.position, vertex.position))
                {
                    var chain = FindCollapsedChain(vertex);
                    intersectionEvent.chains.Add(chain);
                    vertex = chain[chain.Count - 1].next;
                }
                else
                {
                    vertex = vertex.next;
                }
            } while (vertex != startVertex);
        }
        /// <summary>
        /// Computes the intersection of one or more line strings.
        /// </summary>
        public void Compute()
        {
            // source: http://geomalgorithms.com/a09-_intersect-3.html

            _intersections = new List <Coordinate>();
            _edgeIndices   = new List <Tuple <Int32, Int32> >();
            Event              currentEvent = _eventQueue.Next();
            SweepLineSegment   segment;
            IList <Coordinate> intersections;

            while (currentEvent != null)
            {
                if (currentEvent is EndPointEvent)
                {
                    EndPointEvent endPointEvent = (EndPointEvent)currentEvent;
                    switch (endPointEvent.Type)
                    {
                    // Left endpoint event: check for possible intersection with below and / or above segments.
                    case EventType.Left:
                        segment = _sweepLine.Add(endPointEvent);
                        if (segment.Above != null)
                        {
                            intersections = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate,
                                                                        segment.Above.LeftCoordinate, segment.Above.RightCoordinate,
                                                                        PrecisionModel);

                            if (intersections.Count > 0)
                            {
                                IntersectionEvent intersectionEvent = new IntersectionEvent
                                {
                                    Vertex = intersections[0],
                                    Below  = segment,
                                    Above  = segment.Above
                                };
                                _eventQueue.Add(intersectionEvent);
                            }
                        }
                        if (segment.Below != null)
                        {
                            intersections = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate,
                                                                        segment.Below.LeftCoordinate, segment.Below.RightCoordinate,
                                                                        PrecisionModel);

                            if (intersections.Count > 0)
                            {
                                IntersectionEvent intersectionEvent = new IntersectionEvent
                                {
                                    Vertex = intersections[0],
                                    Below  = segment.Below,
                                    Above  = segment
                                };
                                _eventQueue.Add(intersectionEvent);
                            }
                        }
                        break;

                    // Right endpoint event: check for possible intersection of the below and above segments.
                    case EventType.Right:
                        segment = _sweepLine.Search(endPointEvent);
                        if (segment != null)
                        {
                            if (segment.Above != null && segment.Below != null)
                            {
                                intersections = LineAlgorithms.Intersection(segment.Above.LeftCoordinate,
                                                                            segment.Above.RightCoordinate,
                                                                            segment.Below.LeftCoordinate,
                                                                            segment.Below.RightCoordinate,
                                                                            PrecisionModel);

                                if (intersections.Count > 0)
                                {
                                    IntersectionEvent intersectionEvent = new IntersectionEvent
                                    {
                                        Vertex = intersections[0],
                                        Below  = segment.Below,
                                        Above  = segment.Above
                                    };
                                    if (!_eventQueue.Contains(intersectionEvent))
                                    {
                                        _eventQueue.Add(intersectionEvent);
                                    }
                                }
                            }
                            _sweepLine.Remove(segment);
                        }
                        break;
                    }
                }

                // Intersection point event: switch the two concerned segments and check for possible intersection with their below and above segments.
                else if (currentEvent is IntersectionEvent)
                {
                    IntersectionEvent intersectionEvent = (IntersectionEvent)currentEvent;

                    /*
                     * Segment order before intersection: segmentBelow <-> segmentAbove <-> segment <-> segmentAboveAbove
                     * Segment order after intersection:  segmentBelow <-> segment <-> segmentAbove <-> segmentAboveAbove
                     */
                    segment = intersectionEvent.Above;
                    SweepLineSegment segmentAbove = intersectionEvent.Below;

                    // Handle closing intersection points when segments (partially) overlap each other.
                    if (intersectionEvent.IsClose)
                    {
                        if (!_sweepLine.IsAdjacent(segment.Edge, segmentAbove.Edge))
                        {
                            _intersections.Add(currentEvent.Vertex);
                            _edgeIndices.Add(Tuple.Create(Math.Min(segment.Edge, segmentAbove.Edge),
                                                          Math.Max(segment.Edge, segmentAbove.Edge)));
                        }
                    }

                    // It is possible that the previously detected intersection point is not a real intersection, because a new segment started between them,
                    // therefore a repeated check is necessary to carry out.
                    else if (_sweepLine.Add(intersectionEvent))
                    {
                        if (!_sweepLine.IsAdjacent(segment.Edge, segmentAbove.Edge))
                        {
                            _intersections.Add(currentEvent.Vertex);
                            _edgeIndices.Add(Tuple.Create(Math.Min(segment.Edge, segmentAbove.Edge),
                                                          Math.Max(segment.Edge, segmentAbove.Edge)));

                            intersections = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate,
                                                                        segmentAbove.LeftCoordinate, segmentAbove.RightCoordinate,
                                                                        PrecisionModel);

                            if (intersections.Count > 1 && !intersections[1].Equals(intersections[0]))
                            {
                                IntersectionEvent newIntersectionEvent = new IntersectionEvent
                                {
                                    Vertex  = intersections[1],
                                    Below   = segment,
                                    Above   = segmentAbove,
                                    IsClose = true,
                                };
                                _eventQueue.Add(newIntersectionEvent);
                            }
                        }

                        if (segmentAbove.Above != null)
                        {
                            intersections = LineAlgorithms.Intersection(segmentAbove.LeftCoordinate, segmentAbove.RightCoordinate,
                                                                        segmentAbove.Above.LeftCoordinate, segmentAbove.Above.RightCoordinate,
                                                                        PrecisionModel);

                            if (intersections.Count > 0 && intersections[0].X >= intersectionEvent.Vertex.X)
                            {
                                IntersectionEvent newIntersectionEvent = new IntersectionEvent
                                {
                                    Vertex = intersections[0],
                                    Below  = segmentAbove,
                                    Above  = segmentAbove.Above
                                };
                                if (!_eventQueue.Contains(newIntersectionEvent))
                                {
                                    _eventQueue.Add(newIntersectionEvent);
                                }
                            }
                        }

                        if (segment.Below != null)
                        {
                            intersections = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate,
                                                                        segment.Below.LeftCoordinate, segment.Below.RightCoordinate,
                                                                        PrecisionModel);

                            if (intersections.Count > 0 && intersections[0].X >= intersectionEvent.Vertex.X)
                            {
                                IntersectionEvent newIntersectionEvent = new IntersectionEvent
                                {
                                    Vertex = intersections[0],
                                    Below  = segment.Below,
                                    Above  = segment
                                };
                                if (!_eventQueue.Contains(newIntersectionEvent))
                                {
                                    _eventQueue.Add(newIntersectionEvent);
                                }
                            }
                        }
                    }
                }

                currentEvent = _eventQueue.Next();
            }
            _hasResult = true;
        }
Beispiel #8
0
 internal void addToFlippedEdgeInfo(int flippedEdgeIndex, Face face, IntersectionEvent intersection)
 {
     Boolean isNew = true;
     for (int k = 0; k < flippedEdgeInfo.Count; k++)
     {
         if (flippedEdgeInfo[k].edge.index == face.faceEdges[flippedEdgeIndex].index)
         {
             flippedEdgeInfo[k].addSecondInfo(face, intersection.PointA);
             isNew = false;
         }
     }
     if (isNew)
     {
         flippedEdgeInfo.Add(new FlippedEdge(face.faceEdges[flippedEdgeIndex], face, intersection.PointA));
     }
 }
Beispiel #9
0
        /// <summary>
        /// Processes the end point event.
        /// </summary>
        /// <param name="endPointEvent">The end point event.</param>
        private void ProcessEndPointEvent(EndPointEvent endPointEvent)
        {
            SweepLineSegment segment;
            Intersection     intersection;

            switch (endPointEvent.Type)
            {
            // left endpoint event: check for possible intersection with below and / or above segments
            case EventType.Left:
                segment = this.sweepLine.Add(endPointEvent);

                if (segment.Above != null)
                {
                    intersection = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate, segment.Above.LeftCoordinate, segment.Above.RightCoordinate, this.PrecisionModel);

                    if (intersection != null)
                    {
                        IntersectionEvent intersectionEvent = new IntersectionEvent
                        {
                            Vertex = intersection.Coordinate,
                            Below  = segment,
                            Above  = segment.Above
                        };
                        this.eventQueue.Add(intersectionEvent);
                    }
                }

                if (segment.Below != null)
                {
                    intersection = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate, segment.Below.LeftCoordinate, segment.Below.RightCoordinate, this.PrecisionModel);

                    if (intersection != null)
                    {
                        IntersectionEvent intersectionEvent = new IntersectionEvent
                        {
                            Vertex = intersection.Coordinate,
                            Below  = segment.Below,
                            Above  = segment
                        };
                        this.eventQueue.Add(intersectionEvent);
                    }
                }

                break;

            // right endpoint event: check for possible intersection of the below and above segments
            case EventType.Right:
                segment = this.sweepLine.Search(endPointEvent);

                if (segment != null)
                {
                    if (segment.Above != null && segment.Below != null)
                    {
                        intersection = LineAlgorithms.Intersection(segment.Above.LeftCoordinate, segment.Above.RightCoordinate, segment.Below.LeftCoordinate, segment.Below.RightCoordinate, this.PrecisionModel);

                        if (intersection != null)
                        {
                            IntersectionEvent intersectionEvent = new IntersectionEvent
                            {
                                Vertex = intersection.Coordinate,
                                Below  = segment.Below,
                                Above  = segment.Above
                            };
                            if (!this.eventQueue.Contains(intersectionEvent))
                            {
                                this.eventQueue.Add(intersectionEvent);
                            }
                        }
                    }

                    this.sweepLine.Remove(segment);
                }

                break;
            }
        }
Beispiel #10
0
        /// <summary>
        /// Processes the intersection event.
        /// </summary>
        /// <param name="intersectionEvent">The intersection event.</param>
        private void ProcessIntersectionEvent(IntersectionEvent intersectionEvent)
        {
            SweepLineSegment segment;
            Intersection     intersection;

            /*
             * segment order before intersection: segmentBelow <-> segmentAbove <-> segment <-> segmentAboveAbove
             * segment order after intersection:  segmentBelow <-> segment <-> segmentAbove <-> segmentAboveAbove
             */
            segment = intersectionEvent.Above;
            SweepLineSegment segmentAbove = intersectionEvent.Below;

            // dandle closing intersection points when segments (partially) overlap each other
            if (intersectionEvent.IsClosing)
            {
                if (!this.sweepLine.IsAdjacent(segment.Edge, segmentAbove.Edge))
                {
                    this.intersections.Add(intersectionEvent.Vertex);
                    this.edgeIndexes.Add(Tuple.Create(Math.Min(segment.Edge, segmentAbove.Edge),
                                                      Math.Max(segment.Edge, segmentAbove.Edge)));
                }
            }

            // it is possible that the previously detected intersection point is not a real intersection, because a new segment started between them,
            // therefore a repeated check is necessary to carry out
            else if (this.sweepLine.Add(intersectionEvent))
            {
                if (!this.sweepLine.IsAdjacent(segment.Edge, segmentAbove.Edge))
                {
                    this.intersections.Add(intersectionEvent.Vertex);
                    this.edgeIndexes.Add(Tuple.Create(Math.Min(segment.Edge, segmentAbove.Edge),
                                                      Math.Max(segment.Edge, segmentAbove.Edge)));

                    intersection = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate, segmentAbove.LeftCoordinate, segmentAbove.RightCoordinate, this.PrecisionModel);

                    if (intersection.Type == IntersectionType.Interval)
                    {
                        IntersectionEvent newIntersectionEvent = new IntersectionEvent
                        {
                            Vertex    = intersection.End,
                            Below     = segment,
                            Above     = segmentAbove,
                            IsClosing = true,
                        };
                        this.eventQueue.Add(newIntersectionEvent);
                    }
                }

                if (segmentAbove.Above != null)
                {
                    intersection = LineAlgorithms.Intersection(segmentAbove.LeftCoordinate, segmentAbove.RightCoordinate, segmentAbove.Above.LeftCoordinate, segmentAbove.Above.RightCoordinate, this.PrecisionModel);

                    if (intersection != null && intersection.Coordinate.X >= intersectionEvent.Vertex.X)
                    {
                        IntersectionEvent newIntersectionEvent = new IntersectionEvent
                        {
                            Vertex = intersection.Coordinate,
                            Below  = segmentAbove,
                            Above  = segmentAbove.Above
                        };
                        if (!this.eventQueue.Contains(newIntersectionEvent))
                        {
                            this.eventQueue.Add(newIntersectionEvent);
                        }
                    }
                }

                if (segment.Below != null)
                {
                    intersection = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate, segment.Below.LeftCoordinate, segment.Below.RightCoordinate, this.PrecisionModel);

                    if (intersection != null && intersection.Coordinate.X >= intersectionEvent.Vertex.X)
                    {
                        IntersectionEvent newIntersectionEvent = new IntersectionEvent
                        {
                            Vertex = intersection.Coordinate,
                            Below  = segment.Below,
                            Above  = segment
                        };
                        if (!this.eventQueue.Contains(newIntersectionEvent))
                        {
                            this.eventQueue.Add(newIntersectionEvent);
                        }
                    }
                }
            }
        }
Beispiel #11
0
        internal void indentifyAllFlippedEdges()
        {
            flippedEdgeInfo = new List <FlippedEdge>();
            for (int i = 0; i < proxyToMesh.faces.Count; i++)
            {
                Face face = proxyToMesh.faces[i];

                Curve curve = face.convertFaceToPolyLine().ToNurbsCurve();
                CurveIntersections intersections = Intersection.CurveSelf(curve, 0.1);
                if (intersections.Count > 0)
                {
                    controller.errorContainer.Add("Flipped edge check: " +
                                                  intersections.Count.ToString() + " intersection(s) found");
                    for (int j = 0; j < intersections.Count; j++)
                    {
                        IntersectionEvent intersection = intersections[j];
                        if (intersection.IsPoint)
                        {
                            int refA = (int)Math.Floor(intersection.ParameterA);
                            int refB = (int)Math.Floor(intersection.ParameterB);
                            if (refB == face.faceEdges.Count)
                            {
                                //has rounded up to the end of the curve
                                //is this possible maybe happening in lots of places
                                //not ideal!!!
                                //refB--;
                            }

                            if (face.faceEdges.Count == 4)
                            {//if 4 add both...
                                List <int> refsToAdd = new List <int>();
                                for (int k = 0; k < 4; k++)
                                {
                                    if (k != refA && k != refB)
                                    {
                                        refsToAdd.Add(k);
                                    }
                                }
                                if (refsToAdd.Count != 2)
                                {
                                }
                                addToFlippedEdgeInfo(refsToAdd[0], face, intersection);
                                addToFlippedEdgeInfo(refsToAdd[1], face, intersection);
                            }
                            else
                            {
                                int flippedEdgeIndex;
                                if (refB - refA == 2)
                                {
                                    flippedEdgeIndex = refB - 1;
                                }
                                else if ((refA + face.faceEdges.Count) - refB == 2)
                                {
                                    flippedEdgeIndex = (refB + 1) % face.faceEdges.Count;
                                }
                                else
                                {
                                    flippedEdgeIndex = -1;
                                    //do not have a simple flipped edge, need to do something else
                                }

                                if (flippedEdgeIndex != -1)
                                {
                                    addToFlippedEdgeInfo(flippedEdgeIndex, face, intersection);
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #12
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from input parameters and
        /// to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            int   porticType  = 0;
            int   trussType   = 0;
            int   typology    = 0;
            int   clHeight    = 0;
            int   crHeight    = 0;
            int   maxHeight   = 0;
            int   spanOne     = 0;
            int   spanTwo     = 0;
            int   clearHeight = 0;
            int   baseType    = 0;
            int   subdCount   = 0;
            int   supType     = 0;
            int   minLength   = 0;
            int   maxLength   = 0;
            Plane inputPlane  = new Plane();

            if (!DA.GetData(0, ref inputPlane))
            {
                return;
            }
            if (!DA.GetData(1, ref typology))
            {
                return;
            }
            if (!DA.GetData(2, ref baseType))
            {
                return;
            }
            if (!DA.GetData(3, ref supType))
            {
                return;
            }
            if (!DA.GetData(4, ref spanOne))
            {
                return;
            }
            if (!DA.GetData(5, ref spanTwo))
            {
                return;
            }
            if (!DA.GetData(6, ref maxHeight))
            {
                return;
            }
            if (!DA.GetData(7, ref clearHeight))
            {
                return;
            }
            if (!DA.GetData(8, ref crHeight))
            {
                return;
            }
            if (!DA.GetData(9, ref clHeight))
            {
                return;
            }
            if (!DA.GetData(10, ref subdCount))
            {
                return;
            }
            if (!DA.GetData(11, ref minLength))
            {
                return;
            }
            if (!DA.GetData(12, ref maxLength))
            {
                return;
            }
            if (!DA.GetData(13, ref porticType))
            {
                return;
            }
            if (!DA.GetData(14, ref trussType))
            {
                return;
            }

            // initialize outputs
            List <Point3d> superiorBasePoints = new List <Point3d>();
            List <Point3d> inferiorBasePoints = new List <Point3d>();


            List <Curve> columnCurves           = new List <Curve>();
            List <Curve> superiorBaseCurves     = new List <Curve>();
            List <Curve> inferiorBaseCurves     = new List <Curve>();
            List <Curve> intermediateCurvesList = new List <Curve>();

            DataTree <Point3d> superiorPoints     = new DataTree <Point3d>();
            DataTree <Point3d> inferiorPoints     = new DataTree <Point3d>();
            DataTree <Curve>   superiorCurves     = new DataTree <Curve>();
            DataTree <Curve>   inferiorCurves     = new DataTree <Curve>();
            DataTree <Curve>   intermediateCurves = new DataTree <Curve>();
            DataTree <Point3d> thickPoints        = new DataTree <Point3d>();
            DataTree <Point3d> straightPoints     = new DataTree <Point3d>();


            List <Vector3d> sideVectors        = new List <Vector3d>();
            List <double>   hypotenusVariables = new List <double>();

            // warren division restrict
            if (trussType == 2 && subdCount % 2 == 1)
            {
                subdCount += 1;
            }

            // get minimum height and its index to select the rest of the elements according to it
            int[] columnHeights = new int[] { clHeight, crHeight };
            // Print("height left: {0} height right: {1}", columnHeights[0], columnHeights[1]);
            int cMinHeight = columnHeights.Min();
            int cMaxHeight = columnHeights.Max();

            // restrict min height to max column height + 200 if typology is curved or piched
            if (maxHeight <= cMaxHeight && typology == 1)
            {
                maxHeight = cMaxHeight + 200;
            }
            else if (maxHeight <= cMaxHeight && (typology == 2 || typology == 3))
            {
                maxHeight = cMaxHeight;
            }

            // get min and max heights indices
            int notSelected = Array.IndexOf(columnHeights, cMaxHeight);
            int index       = Array.IndexOf(columnHeights, cMinHeight);

            // generate superior truss base points
            superiorBasePoints = SuperiorBasePoints(inputPlane, typology, spanOne, spanTwo, maxHeight, ref crHeight, ref clHeight, cMinHeight, cMaxHeight);

            // generate the columns
            columnCurves = ColumnCurves(inputPlane, typology, spanOne, spanTwo, superiorBasePoints, columnCurves);

            // generate superior truss curve
            superiorBaseCurves = GenerateThickCurves(typology, maxHeight, crHeight, clHeight, superiorBasePoints, 0);

            // calculate the clear difference , and if the clear height exceeds minimum column height, restrict it to 200
            // Print("smallest height: {0} index: {1}", cMinHeight, index);
            int difference = ComputeClearHeight(typology, maxHeight, ref clearHeight, cMinHeight);

            // ====== generate inferior truss points & curves ======= //

            // compute the offset variable
            double offsetFactor = ComputeOffset(index, difference, superiorBaseCurves[index]);

            // compute and store the normal vectors at each point
            List <Vector3d> normalVectors = GetFirstLastNormalVectors(typology, superiorBaseCurves);

            sideVectors.Add(normalVectors[0]);
            sideVectors.Add(normalVectors[2]);
            normalVectors[1].Rotate(-0.5 * Math.PI, Vector3d.YAxis);

            // compute highest hypotenus and middle hypotenus
            double middleHypotenus = ComputeCenterHypotenus(offsetFactor, superiorBaseCurves[index], normalVectors[1]);
            double hypotenus2      = ComputeCornerHypotenus(notSelected, offsetFactor, superiorBaseCurves[notSelected]);


            // store points at normal vectors at each point
            for (int i = 0; i < normalVectors.Count; i++)
            {
                Point3d tempPt = new Point3d(i != 1 ? offsetFactor * normalVectors[i] + superiorBasePoints[i] : middleHypotenus * normalVectors[i] + superiorBasePoints[i]);
                inferiorBasePoints.Add(tempPt);
            }

            // on each side create the clear point at its corresponding clear height
            for (int i = 0; i < sideVectors.Count; i++)
            {
                Point3d tempPt = new Point3d(i != index ? -hypotenus2 * Vector3d.ZAxis + superiorBasePoints[i == 1 ? 2 : 0] : -difference * Vector3d.ZAxis + superiorBasePoints[i == 1 ? 2 : 0]);
                inferiorBasePoints.Insert(i == 0 ? 0 : 4, tempPt);
            }
            List <Point3d> rigidPoints = new List <Point3d>();
            Point3d        clearPoint  = inferiorBasePoints[index == 0 ? 0 : 4];

            rigidPoints.Add(inferiorBasePoints[0]);
            Point3d counterClearPoint = inferiorBasePoints[notSelected == 0 ? 0 : 4];

            rigidPoints.Add(inferiorBasePoints[4]);
            // Print("count {0}", inferiorBasePoints.Count);
            // generate lower curves
            List <Curve> thickCurvesList = GenerateThickCurves(typology, maxHeight, crHeight, clHeight, inferiorBasePoints, 1);

            List <Curve> straightCurvesList = GenerateStraightCurves(clearPoint, counterClearPoint, superiorBasePoints);

            if (baseType == 1)
            {
                inferiorBaseCurves = thickCurvesList;
            }
            else
            {
                inferiorBaseCurves = straightCurvesList;
            }
            // Print("count {0}", inferiorBaseCurves.Count);

            // compute subdivision count

            List <int> computedDivisions = ComputeDivisions(superiorBaseCurves, subdCount, trussType, minLength, maxLength);


            // iterate on each base curve and divide by count
            for (int i = 0; i < superiorBaseCurves.Count; i++)
            {
                Point3d[]      upperSubdPoints   = new Point3d[] { };
                List <Point3d> tempIntersections = new List <Point3d>();

                List <Point3d> thickPointsList    = new List <Point3d>();
                List <Point3d> straightPointsList = new List <Point3d>();
                Curve          top_crv            = superiorBaseCurves[i];
                Curve          bottom_crv         = inferiorBaseCurves[i];

                GH_Path path = new GH_Path(i);
                // store parameters t on top_crv for each point
                double[] subdParameters = top_crv.DivideByCount(computedDivisions[i], true, out upperSubdPoints);
                for (int j = 0; j < upperSubdPoints.Length; j++)
                {
                    if (trussType <= 1 || baseType == 0)
                    {
                        Plane yzPlane = new Plane(upperSubdPoints[j], Vector3d.ZAxis, Vector3d.YAxis);
                        var   events  = Intersection.CurvePlane(Curve.JoinCurves(inferiorBaseCurves)[0], yzPlane, 0.001);
                        if (events != null)
                        {
                            IntersectionEvent cpx_event = new IntersectionEvent();
                            for (int k = 0; k < events.Count; k++)
                            {
                                cpx_event = events[k];
                            }
                            if (j == upperSubdPoints.Length - 1 && typology == 3 && baseType == 1)
                            {
                                tempIntersections.Add(inferiorBasePoints[2]);
                            }
                            else
                            {
                                tempIntersections.Add(cpx_event.PointA);
                            }
                        }
                    }
                    else
                    {
                        double t;
                        bottom_crv.ClosestPoint(upperSubdPoints[j], out t, 0);
                        Point3d tempPoint = bottom_crv.PointAt(t);
                        Point3d endPt     = bottom_crv.PointAtLength(bottom_crv.GetLength());
                        if (j != upperSubdPoints.Length - 1)
                        {
                            tempIntersections.Add(tempPoint);
                        }
                        else
                        {
                            tempIntersections.Add(endPt);
                        }
                    }
                    if (baseType == 1)
                    {
                        thickPointsList = tempIntersections;
                    }
                    else
                    {
                        straightPointsList = tempIntersections;
                    }
                }
                superiorPoints.AddRange(upperSubdPoints, path);
                thickPoints.AddRange(thickPointsList, path);
                straightPoints.AddRange(straightPointsList, path);
            }

            // generate straight inferior Points
            if (baseType == 0)
            {
                inferiorPoints     = straightPoints;
                inferiorBaseCurves = straightCurvesList;
            }
            // generate thickened inferior points
            else
            {
                inferiorPoints     = thickPoints;
                inferiorBaseCurves = thickCurvesList;
            }
            List <Point3d> tempSuperiorPoints = new List <Point3d>();
            List <Point3d> tempInferiorPoints = new List <Point3d>();
            List <Curve>   superiorCurvesList = new List <Curve>();
            List <Curve>   inferiorCurvesList = new List <Curve>();

            // get intermediate connections by truss type
            for (int i = 0; i < superiorBaseCurves.Count; i++)
            {
                tempSuperiorPoints = superiorPoints.Branch(i);
                tempInferiorPoints = inferiorPoints.Branch(i);
                List <Curve> tempIntermediateList = new List <Curve>();

                for (int j = 0; j < tempSuperiorPoints.Count; j++)
                {
                    int[] path  = new int[] { i, j };
                    Line  line1 = new Line();
                    Line  line2 = new Line();
                    Line  line3 = new Line();
                    // HOWE
                    if (trussType == 0)
                    {
                        if (supType == 1)
                        {
                            if (j != 0)
                            {
                                line1 = new Line(tempSuperiorPoints[j], tempInferiorPoints[j - 1]);
                            }
                            if (j != 0)
                            {
                                line2 = new Line(tempSuperiorPoints[j], tempInferiorPoints[j]);
                            }
                        }
                        else
                        {
                            if (j > 1)
                            {
                                line1 = new Line(tempSuperiorPoints[j], tempInferiorPoints[j - 1]);
                            }
                            if (j == 0)
                            {
                                line1 = new Line(tempSuperiorPoints[j], tempInferiorPoints[j + 1]);
                            }
                            if (j != 0)
                            {
                                line2 = new Line(tempSuperiorPoints[j], tempInferiorPoints[j]);
                            }
                        }
                    }

                    // PRATT
                    else if (trussType == 1)
                    {
                        if (j != 0)
                        {
                            line1 = new Line(tempSuperiorPoints[j], tempInferiorPoints[j]);
                        }
                        if (j != tempSuperiorPoints.Count - 1)
                        {
                            line2 = new Line(tempSuperiorPoints[j], tempInferiorPoints[j + 1]);
                        }
                    }

                    // WARREN
                    else if (trussType == 2 && j % 2 == 0)
                    {
                        if (j != tempSuperiorPoints.Count - 1)
                        {
                            line1 = new Line(tempSuperiorPoints[j], tempInferiorPoints[j + 1]);
                        }
                        if (j != 0)
                        {
                            line2 = new Line(tempSuperiorPoints[j], tempInferiorPoints[j - 1]);
                        }
                    }

                    // WARREN INTERLOCK
                    else if (trussType == 3)
                    {
                        if (j % 2 == 0)
                        {
                            if (j != tempSuperiorPoints.Count - 1)
                            {
                                line1 = new Line(tempSuperiorPoints[j], tempInferiorPoints[j + 1]);
                            }
                            if (j != 0)
                            {
                                line3 = new Line(tempSuperiorPoints[j], tempInferiorPoints[j - 1]);
                            }
                        }
                        else
                        {
                            line2 = new Line(tempSuperiorPoints[j], tempInferiorPoints[j]);
                        }
                    }
                    if (line1.Length != 0)
                    {
                        tempIntermediateList.Add(line1.ToNurbsCurve());
                    }
                    if (line2.Length != 0)
                    {
                        tempIntermediateList.Add(line2.ToNurbsCurve());
                    }
                    if (trussType == 3 && line3.Length != 0)
                    {
                        tempIntermediateList.Add(line3.ToNurbsCurve());
                    }
                }
                intermediateCurves.AddRange(tempIntermediateList);
            }
            intermediateCurvesList = intermediateCurves.Branch(0);
            //DataTree<Point3d> quotationPoints = QuotationPoints(superiorBasePoints);

            // get superior and inferior connections by truss type

            superiorPoints.Branch(1).Reverse();
            superiorPoints.Branch(1).RemoveAt(0);
            superiorPoints.Flatten(null);
            List <Point3d> superiorPointsList = superiorPoints.Branch(0);

            // Print("{0}", superiorPointsList.Count);
            inferiorPoints.Branch(1).Reverse();
            inferiorPoints.Branch(1).RemoveAt(0);
            inferiorPoints.Flatten(null);
            List <Point3d> inferiorPointsList = inferiorPoints.Branch(0);

            // Print("{0}", inferiorPointsList.Count);
            if (trussType > 1 && baseType == 1)
            {
                inferiorPointsList.Insert(0, inferiorBasePoints[0]);
                inferiorPointsList.Insert(inferiorPointsList.Count, inferiorBasePoints[4]);
            }

            //for (int i = 0; i < superiorPointsList.Count; i++)
            //{
            //    Line supCurve = new Line();

            //    if (trussType != 2)
            //    {
            //        if (i != superiorPointsList.Count - 1)
            //        {
            //            supCurve = new Line(superiorPointsList[i], superiorPointsList[i + 1]);
            //        }
            //    }
            //    else if (trussType == 2)
            //    {

            //        if (i % 2 == 0 && i != superiorPointsList.Count - 1)
            //        {
            //            supCurve = new Line(superiorPointsList[i], superiorPointsList[i + 2]);
            //        }

            //    }
            //    if (supCurve.IsValid && supCurve.Length != 0)
            //    {
            //        superiorCurvesList.Add(supCurve.ToNurbsCurve());
            //    }
            //}

            //for (int i = 0; i < inferiorPointsList.Count; i++)
            //{
            //    Line infCurve = new Line();

            //    if (trussType <= 1)
            //    {
            //        if (i != inferiorPointsList.Count - 1)
            //        {
            //            infCurve = new Line(inferiorPointsList[i], inferiorPointsList[i + 1]);
            //        }
            //    }
            //    else if (trussType == 2)
            //    {
            //        if (baseType == 0)
            //        {
            //            if (i < 1) infCurve = new Line(inferiorPointsList[i], inferiorPointsList[i + 1]);
            //            else if (i == inferiorPointsList.Count - 2) infCurve = new Line(inferiorPointsList[i], inferiorPointsList[i + 1]);
            //            else if (i % 2 == 1)
            //            {
            //                infCurve = new Line(inferiorPointsList[i], inferiorPointsList[i + 2]);
            //            }
            //        }
            //        else
            //        {
            //            if (i % 2 == 0)
            //            {
            //                if (i != inferiorPointsList.Count - 1) infCurve = new Line(inferiorPointsList[i], inferiorPointsList[i + 2]);
            //            }
            //        }
            //    }
            //    else if (trussType == 3)
            //    {
            //        if (baseType == 0)
            //        {
            //            if (i % 2 == 1 && i < inferiorPointsList.Count - 2) infCurve = new Line(inferiorPointsList[i], inferiorPointsList[i + 2]);
            //            else if (i <= 0 || i == inferiorPointsList.Count - 2) infCurve = new Line(inferiorPointsList[i], inferiorPointsList[i + 1]);
            //        }
            //        else
            //        {
            //            if (i % 2 == 0 && i < inferiorPointsList.Count - 1) infCurve = new Line(inferiorPointsList[i], inferiorPointsList[i + 2]);
            //        }
            //    }
            //    if (infCurve.IsValid && infCurve.Length != 0)
            //    {
            //        inferiorCurvesList.Add(infCurve.ToNurbsCurve());
            //    }
            //}
            if (supType == 0)
            {
                List <Curve> tempList = inferiorBaseCurves;
                //inferiorBaseCurves = new List<Curve>();
                //inferiorCurvesList.RemoveAt(0);
                //inferiorCurvesList.RemoveAt(inferiorCurvesList.Count - 1);
                //for (int i = 0; i < tempList.Count; i++)
                //{
                //    double t;
                //    tempList[i].ClosestPoint(inferiorPointsList[i == 0 ? 1 : inferiorPointsList.Count - 2], out t);
                //    inferiorBaseCurves.Add(tempList[i].Split(t)[1]);
                //}
                //inferiorPointsList.RemoveAt(0);
                //inferiorPointsList.RemoveAt(inferiorPointsList.Count - 1);
            }

            if (porticType == 1)
            {
                DA.SetDataList(0, columnCurves);
                DA.SetDataList(1, superiorBaseCurves);
                DA.SetDataList(2, superiorPointsList);
                DA.SetDataList(3, inferiorBaseCurves);
                DA.SetDataList(4, inferiorPointsList);
                DA.SetDataList(5, intermediateCurvesList);
            }
            else
            {
                DA.SetDataList(0, columnCurves);
                DA.SetDataList(1, superiorBaseCurves);
                DA.SetDataList(2, superiorPointsList);
            }
        }