Example #1
0
 public void VisitEnd(EndType end)
 {
     if (m_details.Length > 0)
     {
         Reporter.TypeFailed(end.Type, CheckID, m_details);
     }
 }
Example #2
0
        //------------------------------------------------------------------------------

        public void AddPaths(List <List <IntPoint> > paths, JoinType joinType, EndType endType)
        {
            foreach (List <IntPoint> p in paths)
            {
                AddPath(p, joinType, endType);
            }
        }
 public void VisitEnd(EndType end)
 {
     if (m_needsCheck && m_hasBadField)
     {
         Reporter.TypeFailed(end.Type, CheckID, m_details);
     }
 }
Example #4
0
    private static ZigZagEval GetZigZagEval <TQuote>(
        EndType endType,
        int index,
        TQuote q)
        where TQuote : IQuote
    {
        ZigZagEval eval = new()
        {
            Index = index
        };

        // consider `type`
        switch (endType)
        {
        case EndType.Close:

            eval.Low  = q.Close;
            eval.High = q.Close;
            break;

        case EndType.HighLow:

            eval.Low  = q.Low;
            eval.High = q.High;
            break;

        default:
            break;
        }

        return(eval);
    }
Example #5
0
    // Show final window with "Retry" button
    // and maximum of points you`ve collected
    public void ShowEndGameWindow(EndType type)
    {
        _endWindow.SetActive(true);
        switch (type)
        {
        case EndType.Comleted:
            _logoText.text = "Completed";
            break;

        case EndType.Failure:
            _logoText.text = "Game Over";
            break;
        }
        _maxPointsText.text            = _saveController.GetMaxPointValue().ToString();
        _yourPointsText.text           = _pointController.Points.ToString();
        _difficultySlider.interactable = true;
        _mainController.SetActive(false);

        var arr = CentipedeController.controllers;

        foreach (CentipedeController cc in arr)
        {
            if (cc != null)
            {
                cc.StopAllCoroutines();
            }
        }

        _saveController.SavePoints(_mainController.GetComponent <PointsController>().Points);
    }
Example #6
0
 public void VisitEnd(EndType end)
 {
     if (!m_disposable && m_hasDispose)
     {
         Reporter.TypeFailed(end.Type, CheckID, string.Empty);
     }
 }
        protected internal virtual Path FilterStrokePath(Path path, Matrix ctm, float lineWidth, int lineCapStyle,
                                                         int lineJoinStyle, float miterLimit, LineDashPattern lineDashPattern)
        {
            JoinType joinType = GetJoinType(lineJoinStyle);
            EndType  endType  = GetEndType(lineCapStyle);

            if (lineDashPattern != null)
            {
                if (IsZeroDash(lineDashPattern))
                {
                    return(new Path());
                }

                if (!IsSolid(lineDashPattern))
                {
                    path = ApplyDashPattern(path, lineDashPattern);
                }
            }

            ClipperOffset offset = new ClipperOffset(miterLimit, PdfCleanUpProcessor.ArcTolerance * PdfCleanUpProcessor.FloatMultiplier);

            AddPath(offset, path, joinType, endType);

            PolyTree resultTree = new PolyTree();

            offset.Execute(ref resultTree, lineWidth * PdfCleanUpProcessor.FloatMultiplier / 2);

            return(FilterFillPath(ConvertToPath(resultTree), ctm, PathPaintingRenderInfo.NONZERO_WINDING_RULE));
        }
Example #8
0
        /// <summary>
        /// Processes an end of line to determine wether it is part of a folding white space, 
        ///  an end of field or an end of header.
        ///  assumes a Carriage return (x0D) has just been read from the "reader".
        /// </summary>
        /// <param name="reader">BufferdByteReader to acces the underlying stream</param>
        /// <returns>Enum EndType</returns>
        internal async Task<FieldValue.EndType> ProcessEol(BufferedByteReader reader)
        {
            var rs = await reader.ReadByteAsync();
            if (rs != (byte)FieldValue.SpecialByte.Linefeed)
            {
                throw new FormatException("carriagereturn must be followed by linefeed");
            }
            _endType = FieldValue.EndType.EndOfField; // unless folowed by a space ( a folding white space = FWS)
            rs = await reader.ReadByteAhead();
            if (rs == (byte)FieldValue.SpecialByte.Space)
            {
                rs = await reader.ReadByteAhead();
                while (rs == (byte)FieldValue.SpecialByte.Space)
                {
                    rs = await reader.ReadByteAhead();
                }
                _endType = FieldValue.EndType.None; // unless folowed by a crlf (End of header)
                // leave 1 space and the not space character on the buffer
                if (reader.BufferSize > 2) reader.RemoveFirst(reader.BufferSize - 2);
            }
            // Two crlf's with or without spaces in between signify te end of the Header 
            if (rs != (byte)FieldValue.SpecialByte.CarriageReturn) return _endType;

            reader.Clear();
            rs = await reader.ReadByteAsync();
            if (rs != (byte)FieldValue.SpecialByte.Linefeed)
            {
                throw new FormatException("carriagereturn must be followed by linefeed");
            }
            _endType = EndType.EndOfHeader;
            return _endType;
        }
Example #9
0
        void UpdateScoreByGameEnd(EndType end)
        {
            if (end != EndType.PROTEST_OPP)
            {
                return;
            }

            var avgScorePerWeek = Mathf.RoundToInt((float)Modeler.Game.score / Modeler.Week.weekNumber);
            var weeksLeft       = Consts.Balance.END_WEEK - Modeler.Week.weekNumber;

            Modeler.Game.score += weeksLeft * avgScorePerWeek;

            if (PlayServicer.IsAuth)
            {
                Rank = -1;
                PlayGamesPlatform.Instance.ReportScore(Modeler.Game.score, GPGSIds.leaderboard_top_operators,
                                                       delegate(bool isOk)
                {
                    if (isOk)
                    {
                        LoadRank();
                    }
                });
            }
        }
Example #10
0
        //------------------------------------------------------------------------------

        public void AddPaths(Paths paths, JoinType jt, EndType et)
        {
            foreach (Path p in paths)
            {
                AddPath(p, jt, et);
            }
        }
Example #11
0
    // calculate brick size
    private static int GetNewBricks <TQuote>(
        EndType endType,
        TQuote q,
        decimal lastOpen,
        decimal brickSize)
        where TQuote : IQuote
    {
        switch (endType)
        {
        case EndType.Close:

            return((int)((q.Close - lastOpen) / brickSize));

        case EndType.HighLow:

            // high/low assumption: absolute greater diff wins
            // --> does not consider close direction

            decimal hQty = (q.High - lastOpen) / brickSize;
            decimal lQty = (q.Low - lastOpen) / brickSize;

            return((int)(Math.Abs(hQty) >= Math.Abs(lQty) ? hQty : lQty));

        default: return(0);
        }
    }
Example #12
0
        /// <summary>
        /// Offset this polyline by the specified amount.
        /// </summary>
        /// <param name="offset">The amount to offset.</param>
        /// <param name="endType">The closure type to use on the offset polygon.</param>
        /// <param name="tolerance">An optional tolerance.</param>
        /// <returns>A new closed Polygon offset in all directions by offset from the polyline.</returns>
        public virtual Polygon[] Offset(double offset, EndType endType, double tolerance = Vector3.EPSILON)
        {
            var clipperScale = 1.0 / tolerance;
            var path         = this.ToClipperPath(tolerance);

            var solution = new List <List <IntPoint> >();
            var co       = new ClipperOffset();

            ClipperLib.EndType clEndType;
            switch (endType)
            {
            case EndType.Butt:
                clEndType = ClipperLib.EndType.etOpenButt;
                break;

            case EndType.ClosedPolygon:
                clEndType = ClipperLib.EndType.etClosedPolygon;
                break;

            case EndType.Square:
            default:
                clEndType = ClipperLib.EndType.etOpenSquare;
                break;
            }
            co.AddPath(path, JoinType.jtMiter, clEndType);
            co.Execute(ref solution, offset * clipperScale);  // important, scale also used here

            var result = new Polygon[solution.Count];

            for (var i = 0; i < result.Length; i++)
            {
                result[i] = solution[i].ToPolygon(tolerance);
            }
            return(result);
        }
        private ModelBaseCore ShowNodeInitialForm(string nodeName, EndType nodeType)
        {
            switch (nodeType)
            {
            case EndType.PPC:
                Component_PPCInitForm ppcForm = new Component_PPCInitForm(nodeName);
                ppcForm.ShowDialog();
                if (ppcForm.DialogResult == DialogResult.Yes)
                {
                    return(ppcForm._ppc);
                }
                break;

            case EndType.FPGA:
                Component_FPGAInitForm fpgaForm = new Component_FPGAInitForm(nodeName);
                fpgaForm.ShowDialog();
                if (fpgaForm.DialogResult == DialogResult.Yes)
                {
                    return(fpgaForm._fpga);
                }
                break;

            default:    //ComputeNodeType.ZYNQ
                Component_ZYNQInitForm zynqForm = new Component_ZYNQInitForm(nodeName);
                zynqForm.ShowDialog();
                if (zynqForm.DialogResult == DialogResult.Yes)
                {
                    return(zynqForm._zynq);
                }
                break;
            }
            return(null);
        }
Example #14
0
 public void VisitEnd(EndType end)
 {
     if (m_needsCheck)
     {
         m_table.Add(end.Type, m_refs);
     }
 }
    public void GiveAnswer(int answer)
    {
        answer--; // Decrement to fit with zero-based index
        answerBox.SetActive(false);

        // If printing answer, do a trick and add the answer to the current dialogueList
        if (printAnswers == true)
        {
            dialogueList.Add(answerList[answer]);
            answerList.Clear();
            endType             = EndType.newDialouge;
            nextDialougeDefault = nextDialogueList[answer];
            Next();

            if (speakerName.Length > 0)
            {
                speakerName   = playerName;
                nameText.text = speakerName;
                nameBox.SetActive(true);
            }
            else
            {
                nameBox.SetActive(false);
            }
        }
        else if (nextDialogueList[answer] != null)
        {
            if (dialogueLog != null)
            {
                dialogueLog.LogText(dialogueList[dialogueIndex], speakerName);
                dialogueLog.LogText(answerList[answer], playerName);
            }
            NextDialogue(nextDialogueList[answer]);
        }
    }
Example #16
0
 public void VisitEnd(EndType type)
 {
     if (m_needsCheck && m_foundZero && !m_foundNone)
     {
         Reporter.TypeFailed(type.Type, CheckID, string.Empty);
     }
 }
 public void VisitEnd(EndType end)
 {
     if (m_hasAdd && m_hasMinus && !m_hasEquals)
     {
         Reporter.TypeFailed(end.Type, CheckID, string.Empty);
     }
 }
Example #18
0
        public virtual void PrintAssociation(string type1, string label1, EndType endType1,
                                             string type2, string label2, EndType endType2,
                                             string name, int size = 2, LinePattern pattern = LinePattern.Solid)
        {
            this.printer.Print(type1);

            if (!string.IsNullOrEmpty(label1))
            {
                this.printer.PrintFormat(" \"{0}\"", label1);
            }

            this.printer.PrintFormat(" {0}{1}{2}",
                                     endType1.GetLeftSymbol(),
                                     pattern.GetSymbol().Repit(size),
                                     endType2.GetRightSymbol());

            if (!string.IsNullOrEmpty(label2))
            {
                this.printer.PrintFormat(" \"{0}\"", label2);
            }

            this.printer.PrintFormat(" {0}", type2);

            if (!string.IsNullOrEmpty(name))
            {
                this.printer.PrintFormat(" : {0}", name);
            }
            this.printer.PrintLn();
        }
Example #19
0
 public void VisitEnd(EndType end)
 {
     if (m_needsCheck && m_foundCompare && !m_foundEquals)
     {
         Reporter.TypeFailed(end.Type, CheckID, string.Empty);
     }
 }
Example #20
0
 public void VisitEnd(EndType end)
 {
     if (!m_disposable && m_ownsField && m_details.Length > 0)
     {
         Reporter.TypeFailed(end.Type, CheckID, "Field: " + m_details);
     }
 }
Example #21
0
    public void playAnim()
    {
        GetComponent <Animation>().Play();
        setFalseVoyeur();
        EndType endType = GameController.endType;

        switch (endType)
        {
        case EndType.Level:
            next.SetActive(value: true);
            collect.SetActive(value: false);
            return;

        case EndType.Hidden:
            next.SetActive(value: false);
            collect.SetActive(value: true);
            GameMenuController.instance.setGoldAmount(100);
            PlayerPrefsManager.SetLastPlayedMode(GameMode.NORMAL);
            return;
        }
        next.SetActive(value: false);
        collect.SetActive(value: true);
        if (endType == EndType.Set)
        {
            GameMenuController.instance.setGoldAmount(25);
        }
        else
        {
            GameMenuController.instance.setGoldAmount(125);
        }
    }
Example #22
0
 public void VisitEnd(EndType end)
 {
     if (m_hasFinalizer && m_hasIntPtrField)
     {
         Reporter.TypeFailed(end.Type, CheckID, string.Empty);
     }
 }
Example #23
0
 public void AddPaths(PolygonPath paths, JoinType joinType, EndType endType)
 {
     foreach (var p in paths)
     {
         AddPath(p, joinType, endType);
     }
 }
Example #24
0
    public RoadNode(bool up, GameObject NW, GameObject ES, EndType top, EndType bottom, Vector2 location, bool used)
    {
        this.up       = up;
        blockNW       = NW;
        blockES       = ES;
        endTop        = top;
        endBottom     = bottom;
        this.location = location;

        if (this.up)
        {
            this.angle = 0;
        }
        else
        {
            this.angle = 90;
        }

        GameObject road = GameStateController.Instance.GetComponent <BuildingPrefabWrapper>().road;

        road.GetComponent <Road_Info>().setLocation((int)location.x, (int)location.y);
        road.GetComponent <Road_Info>().setUsed(used);

        GameObject.Instantiate(GameStateController.Instance.GetComponent <BuildingPrefabWrapper>().road, new Vector3((int)(location.x * 2.5f * 10.0f), 0.0f, (int)(location.y * 2.5f * 10.0f)), Quaternion.Euler(new Vector3(0, (int)angle, 0)), null);
    }
Example #25
0
        public void SwapEndpoints()
        {
            var temp = Start;

            Start = End;
            End   = temp;

            // swap the end cap flag as well (but not the corner type)
            var startHadEndCap = StartType.HasFlag(RoadType.EndCap);
            var endHadEndCap   = EndType.HasFlag(RoadType.EndCap);

            if (endHadEndCap)
            {
                StartType |= RoadType.EndCap;
            }
            else
            {
                StartType &= ~RoadType.EndCap;
            }

            if (startHadEndCap)
            {
                EndType |= RoadType.EndCap;
            }
            else
            {
                EndType &= ~RoadType.EndCap;
            }
        }
Example #26
0
        /// <summary>
        /// Generates a solid outline of the path.
        /// </summary>
        /// <param name="path">the path to outline</param>
        /// <param name="width">The final width outline</param>
        /// <param name="jointStyle">The style to render the joints.</param>
        /// <param name="endCapStyle">The style to render the end caps of open paths (ignored on closed paths).</param>
        /// <returns>A new path representing the outline.</returns>
        public static IPath GenerateOutline(this IPath path, float width, JointStyle jointStyle = JointStyle.Square, EndCapStyle endCapStyle = EndCapStyle.Square)
        {
            var offset = new ClipperOffset()
            {
                MiterLimit = MiterOffsetDelta
            };

            JoinType style           = Convert(jointStyle);
            EndType  openEndCapStyle = Convert(endCapStyle);

            // Pattern can be applied to the path by cutting it into segments
            IEnumerable <ISimplePath> paths = path.Flatten();

            foreach (ISimplePath p in paths)
            {
                IReadOnlyList <PointF> vectors = p.Points;
                var points = new List <IntPoint>(vectors.Count);
                foreach (Vector2 v in vectors)
                {
                    points.Add(new IntPoint(v.X * ScalingFactor, v.Y * ScalingFactor));
                }

                EndType type = p.IsClosed ? EndType.etClosedLine : openEndCapStyle;

                offset.AddPath(points, style, type);
            }

            return(ExecuteOutliner(width, offset));
        }
Example #27
0
 public void VisitEnd(EndType end)
 {
     if (m_isAbstract && m_hasPublicCtor)
     {
         Reporter.TypeFailed(end.Type, CheckID, string.Empty);
     }
 }
Example #28
0
 private void levelEnd()
 {
     endType = getEndType();
     UnityEngine.Debug.Log(endType);
     if (game.mode != GameMode.ADVENTURE)
     {
         SoundManager.instance.GameWin();
     }
     if (game.mode == GameMode.NORMAL)
     {
         if (levelToOpen == -1)
         {
             PlayerPrefsManager.SetLevel(PlayerPrefsManager.GetLevel() + 1);
             PlayerPrefsManager.SetBrilliance(PlayerPrefsManager.GetBrilliance() + 1);
             PlayerPrefsManager.ResetProHint();
             FirebaseController.SendLevelLog();
         }
         else
         {
             levelToOpen++;
         }
     }
     Movements.instance.executeWithDelay((Movements.Execute)GameAnimController.instance.niceTexts, 0.7f);
     if (onGameEnd != null)
     {
         onGameEnd(game);
     }
 }
Example #29
0
        private String IdToName(Board board, EndType endtype, BoardLink link, int id)
        {
            String chipName = String.Empty;

            switch (endtype)
            {
            case EndType.PPC:
                chipName = board.PPCList[id].Name;
                break;

            case EndType.FPGA:
                chipName = board.FPGAList[id].Name;
                break;

            case EndType.ZYNQ:
                chipName = board.ZYNQList[id].Name;
                break;

            case EndType.SW:
                chipName = board.SwitchList[id].Type;
                break;

            case EndType.VPX:
                chipName = Enum.GetName(typeof(LinkType), link.LinkType);
                break;

            default:
                break;
            }
            return(chipName);
        }
Example #30
0
 public void VisitEnd(EndType end)
 {
     if (m_needsCheck && !m_correct)
     {
         Reporter.TypeFailed(end.Type, CheckID, string.Empty);
     }
 }
Example #31
0
        /// <summary>
        /// Adds all iText
        /// <see cref="iText.Kernel.Geom.Subpath"/>
        /// s of the iText
        /// <see cref="iText.Kernel.Geom.Path"/>
        /// to the
        /// <see cref="ClipperOffset"/>
        /// object with one
        /// note: it doesn't add degenerate subpaths.
        /// </summary>
        /// <returns>
        ///
        /// <see cref="System.Collections.IList{E}"/>
        /// consisting of all degenerate iText
        /// <see cref="iText.Kernel.Geom.Subpath"/>
        /// s of the path.
        /// </returns>
        public static IList <Subpath> AddPath(ClipperOffset offset, Path path, JoinType joinType, EndType endType)
        {
            IList <Subpath> degenerateSubpaths = new List <Subpath>();

            foreach (Subpath subpath in path.GetSubpaths())
            {
                if (subpath.IsDegenerate())
                {
                    degenerateSubpaths.Add(subpath);
                    continue;
                }
                if (!subpath.IsSinglePointClosed() && !subpath.IsSinglePointOpen())
                {
                    EndType et;
                    if (subpath.IsClosed())
                    {
                        // Offsetting is never used for path being filled
                        et = EndType.CLOSED_LINE;
                    }
                    else
                    {
                        et = endType;
                    }
                    IList <Point> linearApproxPoints = subpath.GetPiecewiseLinearApproximation();
                    offset.AddPath(new List <IntPoint>(ConvertToLongPoints(linearApproxPoints)), joinType, et);
                }
            }
            return(degenerateSubpaths);
        }
Example #32
0
        //------------------------------------------------------------------------------
        public void AddPath(List<IntPoint> path, JoinType joinType, EndType endType)
        {
            int highI = path.Count - 1;
            if (highI < 0) return;
            PolyNode newNode = new PolyNode();
            newNode.m_jointype = joinType;
            newNode.m_endtype = endType;

            //strip duplicate points from path and also get index to the lowest point ...
            if (endType == EndType.etClosedLine || endType == EndType.etClosedPolygon)
                while (highI > 0 && path[0] == path[highI]) highI--;
            newNode.m_polygon.Capacity = highI + 1;
            newNode.m_polygon.Add(path[0]);
            int j = 0, k = 0;
            for (int i = 1; i <= highI; i++)
                if (newNode.m_polygon[j] != path[i])
                {
                    j++;
                    newNode.m_polygon.Add(path[i]);
                    if (path[i].Y > newNode.m_polygon[k].Y ||
                      (path[i].Y == newNode.m_polygon[k].Y &&
                      path[i].X < newNode.m_polygon[k].X)) k = j;
                }
            if (endType == EndType.etClosedPolygon && j < 2) return;

            m_polyNodes.AddChild(newNode);

            //if this path's lowest pt is lower than all the others then update m_lowest
            if (endType != EndType.etClosedPolygon) return;
            if (m_lowest.X < 0)
                m_lowest = new IntPoint(m_polyNodes.ChildCount - 1, k);
            else
            {
                IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X].m_polygon[(int)m_lowest.Y];
                if (newNode.m_polygon[k].Y > ip.Y ||
                  (newNode.m_polygon[k].Y == ip.Y &&
                  newNode.m_polygon[k].X < ip.X))
                    m_lowest = new IntPoint(m_polyNodes.ChildCount - 1, k);
            }
        }
Example #33
0
 //------------------------------------------------------------------------------
 public void AddPaths(List<List<Point>> paths, JoinType joinType, EndType endType, double eps = double.Epsilon)
 {
     foreach (var p in paths)
     {
         AddPath(p, joinType, endType, eps);
     }
 }
        public static void CalcCylinderTriangles(int numSlices, int numStacks, float radius,
                                                 Vector3 startPoint, Vector3 endPoint,
                                                 bool calcNormals, EndType endType, float endOffSet,
                                                 out Vector3[] pipePoints, out Vector3[] pipeNormals,
                                                 out int[] pipeTris, out Vector3[] endPoints1,
                                                 out Vector3[] endNormals1, out int[] endTris1,
                                                 out Vector3[] endPoints2, out Vector3[] endNormals2,
                                                 out int[] endTris2)
        {
            // get points for cylinder
            pipePoints = CalcCyclinderPoints(numSlices, numStacks, radius, startPoint, endPoint);

            int numTriangles = numSlices * numStacks * 2;

            // build stacks
            int vIdx = 0;
            int pIdx = 0;
            pipeTris = new int[numTriangles * 3];
            int[] pointMulti = new int[pipePoints.Length];
            for (int stack = 0; stack < numStacks; stack++)
            {
                for (int slice = 0; slice < numSlices; slice++)
                {
                    // FIXME: Move multi??
                    pointMulti[pipeTris[vIdx] = pIdx + slice]++;
                    pointMulti[pipeTris[vIdx + 1] = pIdx + slice + 1]++;
                    pointMulti[pipeTris[vIdx + 2] = pIdx + slice + numSlices]++;

                    pointMulti[pipeTris[vIdx + 3] = pIdx + slice]++;
                    pointMulti[pipeTris[vIdx + 4] = pIdx + slice + numSlices]++;
                    pointMulti[pipeTris[vIdx + 5] = pIdx + slice + numSlices - 1]++;

                    vIdx += 6;
                }
                pIdx += numSlices;
            }

            // ends
            if (endType == EndType.Flat)
            {
                int numEndTriangles = numSlices;
                endTris1 = new int[numEndTriangles * 3];
                endPoints1 = new Vector3[numSlices + 1];

                // calc mid points for both ends
                Vector3 cylinderUV = endPoint - startPoint;
                cylinderUV.Normalize();

                Vector3 endP1 = startPoint - (cylinderUV * endOffSet);
                Vector3 endP2 = startPoint/*endPoint*/ + (cylinderUV * endOffSet);

                // copy points
                for (int point = 0; point < endPoints1.Length - 1; point++)
                {
                    endPoints1[point] = pipePoints[point];
                }
                endPoints1[endPoints1.Length - 1] = endP1;

                // first end
                int triIdx = 0;
                int endPIdx = endPoints1.Length - 1;
                for (int point = 0; point < numSlices; point++)
                {
                    endTris1[triIdx] = endPIdx;
                    endTris1[triIdx + 2] = point;
                    if (point == numSlices - 1)
                        endTris1[triIdx + 1] = 0;
                    else
                        endTris1[triIdx + 1] = point + 1;
                    triIdx += 3;
                }

                endTris2 = new int[numEndTriangles * 3];
                endPoints2 = new Vector3[numSlices + 1];

                // copy points
                for (int point = 0; point < endPoints2.Length - 1; point++)
                {
                    endPoints2[point] = pipePoints[point];
                }
                endPoints2[endPoints1.Length - 1] = endP2;
                
                // second end
                for (int point = 0; point < endTris2.Length; point += 3)
                {
                    endTris2[point] = endTris1[point];
                    endTris2[point + 1] = endTris1[point + 2];
                    endTris2[point + 2] = endTris1[point + 1];
                }

                if (calcNormals)
                {
                    endNormals1 = new Vector3[endPoints1.Length];
                    int idx = 0;
                    for (int tri = 0; tri < numEndTriangles; tri++)
                    {
                        Vector3 v0 = endPoints1[endTris1[idx]];
                        Vector3 v1 = endPoints1[endTris1[idx + 2]];
                        Vector3 v2 = endPoints1[endTris1[idx + 1]];

                        Vector3 e1 = v1 - v0, e2 = v2 - v0;
                        Vector3 fNormal = Vector3.Normalize(Vector3.Cross(e1, e2));

                        endNormals1[endTris1[idx]] += fNormal;
                        endNormals1[endTris1[idx + 2]] += fNormal;
                        endNormals1[endTris1[idx + 1]] += fNormal;
                        idx += 3;
                    }
                    for (int point = 0; point < endNormals1.Length - 1; point++)
                    {
                        endNormals1[point] *= 0.5f;//1f / (float)//pointMulti[point];
                    }
                    endNormals1[endNormals1.Length - 1] *= numSlices;

                    endNormals2 = new Vector3[endPoints2.Length];
                    Array.Copy(endNormals1, endNormals2, endNormals1.Length);
                    for (int point = 0; point < endNormals1.Length; point++)
                    {
                        endNormals2[point].Z = - endNormals2[point].Z;
                    }
                    //mult = new int[endPoints2.Length];
                    //idx = 0;
                    //for (int tri = 0; tri < numEndTriangles; tri++)
                    //{
                    //    Vector3 v0 = endPoints2[endTris2[idx]];
                    //    Vector3 v1 = endPoints2[endTris2[idx + 1]];
                    //    Vector3 v2 = endPoints2[endTris2[idx + 2]];

                    //    Vector3 e1 = v1 - v0, e2 = v2 - v0;
                    //    Vector3 fNormal = Vector3.Normalize(Vector3.Cross(e1, e2));

                    //    endNormals2[endTris2[idx]] += fNormal;
                    //    endNormals2[endTris2[idx + 1]] += fNormal;
                    //    endNormals2[endTris2[idx + 2]] += fNormal;
                    //    idx += 3;
                    //}
                    //for (int point = 0; point < endNormals2.Length; point++)
                    //{
                    //    endNormals2[point] *= 1f / (float)pointMulti[point];
                    //}
                }
                else
                {
                    endNormals1 = null;
                    endNormals2 = null;
                }
            }
            else if (endType == EndType.Rounded)
            {
                // build start end cup
                int numEndTriangles = numSlices * 6;
                endPoints1 = new Vector3[(numSlices * 2) + 1];

                // build profile - only heights needed? then maybe scale cylinder outline?
                Vector2[] profile;
                CalcArcPointsCCW(3, 1, new Vector2(0, 0), 90, out profile);

                // extract template to scale from points
                Vector2[] cylinderTemplate = new Vector2[numSlices];
                for (int point = 0; point < numSlices; point++)
                {
                    cylinderTemplate[point] = new Vector2(pipePoints[point].X, pipePoints[point].Y);
                }

                // build points by scale & translate cylinder
                Vector3[] endPoints = new Vector3[numSlices];
                for (int level = 0; level < 1; level++)
                {
                    float scale = profile[level + 1].X;
                    float translation = endOffSet * -profile[level + 1].Y;
                    int epIdx = level * numSlices;
                    for (int point = 0; point < numSlices; point++)
                    {
                        // scale 'x' & 'y', translate 'z'
                        endPoints[point + epIdx] = new Vector3(cylinderTemplate[point].X * scale,
                                                               cylinderTemplate[point].Y * scale,
                                                               translation);
                    }
                }

                // calc mid points for both ends
                Vector3 cylinderUV = endPoint - startPoint;
                cylinderUV.Normalize();

                Vector3 endP1 = startPoint - (cylinderUV * endOffSet);

                // build points
                for (int point = 0; point < numSlices; point++)
                {
                    endPoints1[point] = endPoints[point];
                }
                pIdx = numSlices;
                for (int point = 0; point < numSlices; point++)
                {
                    endPoints1[pIdx++] = pipePoints[point];
                }
                endPoints1[endPoints1.Length - 1] = endP1;

                // flip for other end
                endPoints2 = new Vector3[endPoints1.Length];
                for (int point = 0; point < endPoints2.Length; point++)
                {
                    endPoints2[point] = endPoints1[point];
                    endPoints2[point].Z = -endPoints2[point].Z;
                }

                // build triangles
                endTris1 = new int[numEndTriangles * 3];

                // top cap
                int triIdx = 0;
                int endIdx = endPoints1.Length - 1;
                for (int point = 0; point < numSlices; point++)
                {
                    endTris1[triIdx] = endIdx;
                    if (point < numSlices - 1)
                        endTris1[triIdx + 1] = point + 1;
                    else
                        endTris1[triIdx + 1] = 0;
                    endTris1[triIdx + 2] = point;
                    triIdx += 3;
                }
                // sections
                //for (int section = 0; section < 1; section++)
                //{
                for (int point = 0; point < numSlices; point++)
                {
                    endTris1[triIdx] = point;
                    if (point < numSlices - 1)
                        endTris1[triIdx + 1] = point + numSlices + 1;
                    else
                        endTris1[triIdx + 1] = point + 1;
                    endTris1[triIdx + 2] = point + numSlices;

                    endTris1[triIdx + 3] = point;
                    if (point < numSlices - 1)
                    {
                        endTris1[triIdx + 4] = point + 1;
                        endTris1[triIdx + 5] = point + numSlices + 1;
                    }
                    else
                    {
                        endTris1[triIdx + 4] = 0;
                        endTris1[triIdx + 5] = numSlices;
                    }

                    triIdx += 6;
                }
                //}

                // duplicate for end2
                endTris2 = new int[endTris1.Length];
                for (int point = 0; point < endTris2.Length; point+=3)
                {
                    endTris2[point] = endTris1[point];
                    endTris2[point + 1] = endTris1[point + 2];
                    endTris2[point + 2] = endTris1[point + 1];
                }

                // calc normals
                if (calcNormals)
                {
                    // run multiplicites
                    //int[] multi = new int[endPoints1.Length];
                    //for (int tri = 0; tri < numEndTriangles * 3; tri += 3)
                    //{
                    //    multi[endTris1[tri]]++;
                    //    multi[endTris1[tri + 1]]++;
                    //    multi[endTris1[tri + 2]]++;
                    //}

                    // calc normals
                    endNormals1 = new Vector3[endPoints1.Length];
                    for (int tri = 0; tri < numEndTriangles * 3; tri += 3)
                    {
                        Vector3 v0 = endPoints1[endTris1[tri]];
                        Vector3 v1 = endPoints1[endTris1[tri + 1]];
                        Vector3 v2 = endPoints1[endTris1[tri + 2]];

                        Vector3 e1 = v1 - v0, e2 = v2 - v0;
                        Vector3 fNormal = Vector3.Normalize(Vector3.Cross(e1, e2));

                        endNormals1[endTris1[tri]] += fNormal;
                        endNormals1[endTris1[tri + 1]] += fNormal;
                        endNormals1[endTris1[tri + 2]] += fNormal;
                    }

                    // normalize
                    for (int normal = 0; normal < endNormals1.Length - 1; normal++)
                    {
                        endNormals1[normal] *= 1f / (float)pointMulti[normal];
                    }

                    // copy for flipside and invert Z
                    endNormals2 = new Vector3[endNormals1.Length];
                    Array.Copy(endNormals1, endNormals2, endNormals1.Length);
                    for (int normal = 0; normal < endNormals2.Length; normal++)
                    {
                        endNormals1[normal].Z = -endNormals1[normal].Z;
                    }
                    // NOTE: Does not blend with rest or cylinder - problem?
                }
                else
                {
                    endNormals1 = endNormals2 = null;
                }
            }
            else
            {
                endPoints1 = null;
                endTris1 = null;
                endNormals1 = null;
                endPoints2 = null;
                endTris2 = null;
                endNormals2 = null;
            }

            // calc normals
            if (calcNormals)
            {
                pipeNormals = new Vector3[pipePoints.Length];
                int idx = 0;
                for (int tri=0; tri < numTriangles; tri++)
                {
                    Vector3 v0 = pipePoints[pipeTris[idx]];
                    Vector3 v1 = pipePoints[pipeTris[idx + 1]];
                    Vector3 v2 = pipePoints[pipeTris[idx + 2]];

                    Vector3 e1 = v1 - v0, e2 = v2 - v0;
                    Vector3 fNormal = Vector3.Normalize(Vector3.Cross(e1, e2));

                    pipeNormals[pipeTris[idx]] += fNormal;
                    pipeNormals[pipeTris[idx + 1]] += fNormal;
                    pipeNormals[pipeTris[idx + 2]] += fNormal;

                    idx += 3;
                }
                for (int point = 0; point < pipeNormals.Length; point++)
                {
                    pipeNormals[point] *= 1f / (float)pointMulti[point];
                }
            }
            else
            {
                pipeNormals = null;
                endNormals1 = null;
                endNormals2 = null;
            }
        }
        private static void AddPath(ClipperOffset offset, Path path, JoinType joinType, EndType endType) {
            foreach (Subpath subpath in path.Subpaths) {
                if (!subpath.IsSinglePointClosed() && !subpath.IsSinglePointOpen()) {
                    EndType et;

                    if (subpath.Closed) {
                        // Offsetting is never used for path being filled
                        et = EndType.etClosedLine;
                    } else {
                        et = endType;
                    }

                    IList<Point2D> linearApproxPoints = subpath.GetPiecewiseLinearApproximation();
                    offset.AddPath(ConvertToIntPoints(linearApproxPoints), joinType, et);
                }
            }
        }
        private PolyOffsetBuilder(IReadOnlyList<IReadOnlyList<IntPoint>> points, List<List<IntPoint>> solution, bool isPolygon, double delta, JoinType jointype, EndType endtype, double limit = 0)
        {
            Contract.Requires(points != null);
            Contract.Requires(solution != null);

            if (ReferenceEquals(solution, points))
                throw new ArgumentException("Input and Output parameters cannot be the same", nameof(solution));
            if (delta == 0)
                return;

            _p = points;
            _delta = delta;
            _rmin = 0.5;

            if (jointype == JoinType.Miter)
            {
                if (limit > 2)
                    _rmin = 2.0 / (limit * limit);
                limit = 0.25; //just in case endtype == etRound
            }
            else
            {
                if (limit <= 0)
                    limit = 0.25;
                else if (limit > Math.Abs(delta))
                    limit = Math.Abs(delta);
            }

            solution.Clear();
            for (_i = 0; _i < points.Count; _i++)
            {
                var len = points[_i].Count;
                if (len == 0 || (len < 3 && delta <= 0))
                    continue;
                else if (len == 1)
                {
                    _currentPoly = new List<IntPoint>();
                    _currentPoly = InternalHelpers.BuildArc(points[_i][0], 0, 2 * Math.PI, delta, limit);
                    solution.Add(_currentPoly);
                    continue;
                }

                var forceClose = points[_i][0].Equals(points[_i][len - 1]);
                if (forceClose)
                    len--;

                //build normals ...
                _normals.Clear();
                for (var j = 0; j < len - 1; ++j)
                    _normals.Add(points[_i][j].UnitNormal(points[_i][j + 1]));
                if (isPolygon || forceClose)
                    _normals.Add(points[_i][len - 1].UnitNormal(points[_i][0]));
                else
                    _normals.Add(_normals[len - 2]);

                _currentPoly = new List<IntPoint>();
                if (isPolygon || forceClose)
                {
                    _k = len - 1;
                    for (_j = 0; _j < len; ++_j)
                        OffsetPoint(jointype, limit);
                    solution.Add(_currentPoly);
                    if (!isPolygon)
                    {
                        _currentPoly = new List<IntPoint>();
                        _delta = -_delta;
                        _k = len - 1;
                        for (_j = 0; _j < len; ++_j)
                            OffsetPoint(jointype, limit);
                        _delta = -_delta;
                        _currentPoly.Reverse();
                        solution.Add(_currentPoly);
                    }
                }
                else
                {
                    _k = 0;
                    for (_j = 1; _j < len - 1; ++_j)
                        OffsetPoint(jointype, limit);

                    IntPoint pt1;
                    if (endtype == EndType.OpenButt)
                    {
                        _j = len - 1;
                        pt1 = new IntPoint(InternalHelpers.Round(points[_i][_j].X + _normals[_j].X * delta), InternalHelpers.Round(points[_i][_j].Y + _normals[_j].Y * delta));
                        AddPoint(pt1);
                        pt1 = new IntPoint(InternalHelpers.Round(points[_i][_j].X - _normals[_j].X * delta), InternalHelpers.Round(points[_i][_j].Y - _normals[_j].Y * delta));
                        AddPoint(pt1);
                    }
                    else
                    {
                        _j = len - 1;
                        _k = len - 2;
                        _normals[_j] = new DoublePoint(-_normals[_j].X, -_normals[_j].Y);

                        if (endtype == EndType.OpenSquare)
                            DoSquare();
                        else
                            DoRound(limit);
                    }

                    //re-build Normals ...
                    for (var j = len - 1; j > 0; j--)
                    {
                        _normals[_j] = new DoublePoint(-_normals[j - 1].X, -_normals[j - 1].Y);
                    }
                    _normals[0] = new DoublePoint(-_normals[1].X, -_normals[1].Y);

                    _k = len - 1;
                    for (_j = _k - 1; _j > 0; --_j)
                        OffsetPoint(jointype, limit);

                    if (endtype == EndType.OpenButt)
                    {
                        pt1 = new IntPoint(InternalHelpers.Round(points[_i][0].X - _normals[0].X * delta), InternalHelpers.Round(points[_i][0].Y - _normals[0].Y * delta));
                        AddPoint(pt1);
                        pt1 = new IntPoint(InternalHelpers.Round(points[_i][0].X + _normals[0].X * delta), InternalHelpers.Round(points[_i][0].Y + _normals[0].Y * delta));
                        AddPoint(pt1);
                    }
                    else
                    {
                        _k = 1;
                        if (endtype == EndType.OpenSquare)
                            DoSquare();
                        else
                            DoRound(limit);
                    }
                    solution.Add(_currentPoly);
                }
            }

            //finally, clean up untidy corners ...
            var clpr = new Clipper();
            clpr.AddPolygons(solution, PolyType.Subject);
            if (delta > 0)
            {
                clpr.Execute(ClipType.Union, solution, PolyFillType.Positive, PolyFillType.Positive);
            }
            else
            {
                var r = clpr.GetBounds();
                var outer = new List<IntPoint>(4) {
                    new IntPoint(r.Left - 10, r.Bottom + 10),
                    new IntPoint(r.Right + 10, r.Bottom + 10),
                    new IntPoint(r.Right + 10, r.Top - 10),
                    new IntPoint(r.Left - 10, r.Top - 10)
                };

                clpr.AddPolygon(outer, PolyType.Subject);
                clpr.ReverseSolution = true;
                clpr.Execute(ClipType.Union, solution, PolyFillType.Negative, PolyFillType.Negative);
                if (solution.Count > 0)
                    solution.RemoveAt(0);
            }
        }
        public static void Offset(IReadOnlyList<IReadOnlyList<IntPoint>> points, List<List<IntPoint>> solution, bool isPolygon, double delta, JoinType jointype, EndType endtype, double limit = 0)
        {
            Contract.Requires(points != null);
            Contract.Requires(solution != null);

            //This is ugly as hell! The constructor does all the work, mutates one of it's arguments and returns a useless object (the builder has already been used by this point).

            // ReSharper disable once ObjectCreationAsStatement
            new PolyOffsetBuilder(points, solution, isPolygon, delta, jointype, endtype, limit);
        }
Example #38
0
            //------------------------------------------------------------------------------
            public PolyOffsetBuilder(Polygons pts, Polygons solution, bool isPolygon, double delta,
                JoinType jointype, EndType endtype, double limit = 0)
            {
                //precondition: solution != pts

                if (delta == 0) { solution = pts; return; }
                m_p = pts;
                m_delta = delta;
                m_rmin = 0.5;

                if (jointype == JoinType.jtMiter)
                {
                    if (limit > 2) m_rmin = 2.0 / (limit * limit);
                    limit = 0.25; //just in case endtype == etRound
                }
                else
                {
                    if (limit <= 0) limit = 0.25;
                    else if (limit > Math.Abs(delta)) limit = Math.Abs(delta);
                }

                double deltaSq = delta * delta;
                solution.Clear();
                solution.Capacity = pts.Count;
                for (m_i = 0; m_i < pts.Count; m_i++)
                {
                    int len = pts[m_i].Count;
                    if (len == 0 || (len < 3 && delta <= 0))
                        continue;
                    else if (len == 1)
                    {
                        currentPoly = new Polygon();
                        currentPoly = BuildArc(pts[m_i][0], 0, 2 * Math.PI, delta, limit);
                        solution.Add(currentPoly);
                        continue;
                    }

                    bool forceClose = PointsEqual(pts[m_i][0], pts[m_i][len - 1]);
                    if (forceClose) len--;

                    //build normals ...
                    normals.Clear();
                    normals.Capacity = len;
                    for (int j = 0; j < len - 1; ++j)
                        normals.Add(GetUnitNormal(pts[m_i][j], pts[m_i][j + 1]));
                    if (isPolygon || forceClose)
                        normals.Add(GetUnitNormal(pts[m_i][len - 1], pts[m_i][0]));
                    else
                        normals.Add(new DoublePoint(normals[len - 2]));

                    currentPoly = new Polygon();
                    if (isPolygon || forceClose)
                    {
                        m_k = len - 1;
                        for (m_j = 0; m_j < len; ++m_j)
                            OffsetPoint(jointype, limit);
                        solution.Add(currentPoly);
                        if (!isPolygon)
                        {
                            currentPoly = new Polygon();
                            m_delta = -m_delta;
                            m_k = len - 1;
                            for (m_j = 0; m_j < len; ++m_j)
                                OffsetPoint(jointype, limit);
                            m_delta = -m_delta;
                            currentPoly.Reverse();
                            solution.Add(currentPoly);
                        }
                    }
                    else
                    {
                        m_k = 0;
                        for (m_j = 1; m_j < len - 1; ++m_j)
                            OffsetPoint(jointype, limit);

                        IntPoint pt1;
                        if (endtype == EndType.etButt)
                        {
                            m_j = len - 1;
                            pt1 = new IntPoint((Int64)Round(pts[m_i][m_j].X + normals[m_j].X *
                              delta), (Int64)Round(pts[m_i][m_j].Y + normals[m_j].Y * delta));
                            AddPoint(pt1);
                            pt1 = new IntPoint((Int64)Round(pts[m_i][m_j].X - normals[m_j].X *
                              delta), (Int64)Round(pts[m_i][m_j].Y - normals[m_j].Y * delta));
                            AddPoint(pt1);
                        }
                        else
                        {
                            m_j = len - 1;
                            m_k = len - 2;
                            normals[m_j].X = -normals[m_j].X;
                            normals[m_j].Y = -normals[m_j].Y;
                            if (endtype == EndType.etSquare) DoSquare();
                            else DoRound(limit);
                        }

                        //re-build Normals ...
                        for (int j = len - 1; j > 0; j--)
                        {
                            normals[j].X = -normals[j - 1].X;
                            normals[j].Y = -normals[j - 1].Y;
                        }
                        normals[0].X = -normals[1].X;
                        normals[0].Y = -normals[1].Y;

                        m_k = len - 1;
                        for (m_j = m_k - 1; m_j > 0; --m_j)
                            OffsetPoint(jointype, limit);

                        if (endtype == EndType.etButt)
                        {
                            pt1 = new IntPoint((Int64)Round(pts[m_i][0].X - normals[0].X * delta),
                              (Int64)Round(pts[m_i][0].Y - normals[0].Y * delta));
                            AddPoint(pt1);
                            pt1 = new IntPoint((Int64)Round(pts[m_i][0].X + normals[0].X * delta),
                              (Int64)Round(pts[m_i][0].Y + normals[0].Y * delta));
                            AddPoint(pt1);
                        }
                        else
                        {
                            m_k = 1;
                            if (endtype == EndType.etSquare) DoSquare();
                            else DoRound(limit);
                        }
                        solution.Add(currentPoly);
                    }
                }

                //finally, clean up untidy corners ...
                Clipper clpr = new Clipper();
                clpr.AddPolygons(solution, PolyType.ptSubject);
                if (delta > 0)
                {
                    clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
                }
                else
                {
                    IntRect r = clpr.GetBounds();
                    Polygon outer = new Polygon(4);

                    outer.Add(new IntPoint(r.left - 10, r.bottom + 10));
                    outer.Add(new IntPoint(r.right + 10, r.bottom + 10));
                    outer.Add(new IntPoint(r.right + 10, r.top - 10));
                    outer.Add(new IntPoint(r.left - 10, r.top - 10));

                    clpr.AddPolygon(outer, PolyType.ptSubject);
                    clpr.ReverseSolution = true;
                    clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative);
                    if (solution.Count > 0) solution.RemoveAt(0);
                }
            }
Example #39
0
        //------------------------------------------------------------------------------
        public static Polygons OffsetPolyLines(Polygons lines,
          double delta, JoinType jointype, EndType endtype,
          double limit)
        {
            Polygons result = new Polygons();

            //automatically strip duplicate points because it gets complicated with
            //open and closed lines and when to strip duplicates across begin-end ...
            Polygons pts = new Polygons(lines);
            for (int i = 0; i < pts.Count; ++i)
            {
                for (int j = pts[i].Count - 1; j > 0; j--)
                    if (PointsEqual(pts[i][j], pts[i][j - 1]))
                        pts[i].RemoveAt(j);
            }

            if (endtype == EndType.etClosed)
            {
                int sz = pts.Count;
                pts.Capacity = sz * 2;
                for (int i = 0; i < sz; ++i)
                {
                    Polygon line = new Polygon(pts[i]);
                    line.Reverse();
                    pts.Add(line);
                }
                new PolyOffsetBuilder(pts, result, true, delta, jointype, endtype, limit);
            }
            else
                new PolyOffsetBuilder(pts, result, false, delta, jointype, endtype, limit);

            return result;
        }
Example #40
0
        //------------------------------------------------------------------------------
        public void AddPath(IList<Point> path, JoinType joinType, EndType endType, double eps = double.Epsilon)
        {
            var highI = path.Count - 1;
            if (highI < 0) return;
            var newNode = new PolyNode
            {
                JoinType = joinType,
                EndType = endType,
                Level = 0
            };

            //strip duplicate points from path and also get index to the lowest point ...
            if (endType == EndType.ClosedLine || endType == EndType.ClosedPolygon)
            {
                while (highI > 0 && path[0] == path[highI])
                {
                    highI--;
                }
            }

            var ctr = newNode.Contour;

            ctr.Capacity = highI + 1;
            ctr.Add(path[0]);

            for (var i = 1; i <= highI; i++)
            {
                if (ctr[ctr.Count - 1].DistanceTo(path[i]) > eps)
                {
                    ctr.Add(path[i]);
                }
            }

            if (endType == EndType.ClosedPolygon && ctr.Count < 3)
                return;

            polyNodes.Add(newNode);
        }
Example #41
0
 //------------------------------------------------------------------------------
 public void AddPaths(List<List<IntPoint>> paths, JoinType joinType, EndType endType)
 {
     foreach (List<IntPoint> p in paths)
         AddPath(p, joinType, endType);
 }
Example #42
0
        /**
         * Adds all subpaths of the path to the {@link ClipperOffset} object with one
         * note: it doesn't add degenerate subpaths.
         *
         * @return {@link java.util.List} consisting of all degenerate subpaths of the path.
         */
        private static IList<Subpath> AddPath(ClipperOffset offset, Path path, JoinType joinType, EndType endType) {
            IList<Subpath> degenerateSubpaths = new List<Subpath>();

            foreach (Subpath subpath in path.Subpaths) {
                if (subpath.IsDegenerate()) {
                    degenerateSubpaths.Add(subpath);
                    continue;
                }

                if (!subpath.IsSinglePointClosed() && !subpath.IsSinglePointOpen()) {
                    EndType et;

                    if (subpath.Closed) {
                        // Offsetting is never used for path being filled
                        et = EndType.etClosedLine;
                    } else {
                        et = endType;
                    }

                    IList<Point2D> linearApproxPoints = subpath.GetPiecewiseLinearApproximation();
                    offset.AddPath(ConvertToIntPoints(linearApproxPoints), joinType, et);
                }
            }

            return degenerateSubpaths;
        }
Example #43
0
      //------------------------------------------------------------------------------

      public static Paths OffsetPaths(Paths polys, double delta,
          JoinType jointype, EndType endtype, double MiterLimit)
      {
        Paths out_polys = new Paths(polys.Count);
        IntPoint botPt = new IntPoint();
        IntPoint pt;
        int botIdx = -1;
        for (int i = 0; i < polys.Count; ++i)
        {
          out_polys.Add(new Path());
          if (StripDupsAndGetBotPt(polys[i], out_polys[i], endtype == EndType.etClosed, out pt))
            if (botIdx < 0 || pt.Y > botPt.Y || (pt.Y == botPt.Y && pt.X < botPt.X))
            {
              botPt = pt;
              botIdx = i;
            }
        }
        if (endtype == EndType.etClosed && botIdx >= 0 && !Orientation(out_polys[botIdx]))
          ReversePaths(out_polys);

        Paths result;
        new PolyOffsetBuilder(out_polys, out result, delta, jointype, endtype, MiterLimit);
        return result;
      }
Example #44
0
          //------------------------------------------------------------------------------

          public PolyOffsetBuilder(Paths pts, out Paths solution, double delta,
              JoinType jointype, EndType endtype, double limit = 0)
          {
              //precondition: solution != pts
              solution = new Paths();
              if (ClipperBase.near_zero(delta)) {solution = pts; return; }
              m_p = pts;
              if (endtype != EndType.etClosed && delta < 0) delta = -delta;
              m_delta = delta;

              if (jointype == JoinType.jtMiter)
              {
                  //m_miterVal: see offset_triginometry.svg in the documentation folder ...
                  if (limit > 2) m_miterLim = 2 / (limit * limit);
                  else m_miterLim = 0.5;
                  if (endtype == EndType.etRound) limit = 0.25;
              }
              if (jointype == JoinType.jtRound || endtype == EndType.etRound)
              {
              if (limit <= 0) limit = 0.25;
              else if (limit > Math.Abs(delta)*0.25) limit = Math.Abs(delta)*0.25;
              //m_roundVal: see offset_triginometry2.svg in the documentation folder ...
              m_Steps360 = Math.PI / Math.Acos(1 - limit / Math.Abs(delta));
              m_sin = Math.Sin(2 * Math.PI / m_Steps360);
              m_cos = Math.Cos(2 * Math.PI / m_Steps360);
              m_Steps360 /= Math.PI * 2;
              if (delta < 0) m_sin = -m_sin;
              }

              double deltaSq = delta * delta;
              solution.Capacity = pts.Count;
              for (m_i = 0; m_i < pts.Count; m_i++)
              {
                  int len = pts[m_i].Count;
                  if (len == 0 || (len < 3 && delta <= 0)) continue;
                    
                  if (len == 1)
                  {
                      if (jointype == JoinType.jtRound)
                      {
                          double X = 1.0, Y = 0.0;
                          for (cInt j = 1; j <= Round(m_Steps360 * 2 * Math.PI); j++)
                          {
                              AddPoint(new IntPoint(
                                Round(m_p[m_i][0].X + X * delta),
                                Round(m_p[m_i][0].Y + Y * delta)));
                              double X2 = X;
                              X = X * m_cos - m_sin * Y;
                              Y = X2 * m_sin + Y * m_cos;
                          }
                      }
                      else
                      {
                          double X = -1.0, Y = -1.0;
                          for (int j = 0; j < 4; ++j)
                          {
                              AddPoint(new IntPoint(Round(m_p[m_i][0].X + X * delta),
                                Round(m_p[m_i][0].Y + Y * delta)));
                              if (X < 0) X = 1;
                              else if (Y < 0) Y = 1;
                              else X = -1;
                          }
                      }
                      continue;
                  }
                    
                  //build normals ...
                  normals.Clear();
                  normals.Capacity = len;
                  for (int j = 0; j < len -1; ++j)
                      normals.Add(GetUnitNormal(pts[m_i][j], pts[m_i][j+1]));
                  if (endtype == EndType.etClosed)
                      normals.Add(GetUnitNormal(pts[m_i][len - 1], pts[m_i][0]));
                  else
                      normals.Add(new DoublePoint(normals[len - 2]));

                  currentPoly = new Path();
                  if (endtype == EndType.etClosed)
                  {
                      m_k = len - 1;
                      for (m_j = 0; m_j < len; ++m_j)
                          OffsetPoint(jointype);
                      solution.Add(currentPoly); 
                  }
                  else
                  {
                      m_k = 0;
                      for (m_j = 1; m_j < len - 1; ++m_j)
                          OffsetPoint(jointype);

                      IntPoint pt1;
                      if (endtype == EndType.etButt)
                      {
                          m_j = len - 1;
                          pt1 = new IntPoint((cInt)Round(pts[m_i][m_j].X + normals[m_j].X *
                            delta), (cInt)Round(pts[m_i][m_j].Y + normals[m_j].Y * delta));
                          AddPoint(pt1);
                          pt1 = new IntPoint((cInt)Round(pts[m_i][m_j].X - normals[m_j].X *
                            delta), (cInt)Round(pts[m_i][m_j].Y - normals[m_j].Y * delta));
                          AddPoint(pt1);
                      }
                      else
                      {
                          m_j = len - 1;
                          m_k = len - 2;
                          m_sinA = 0;
                          normals[m_j] = new DoublePoint(-normals[m_j].X, -normals[m_j].Y);
                          if (endtype == EndType.etSquare)
                            DoSquare();
                          else
                            DoRound();
                      }

                      //re-build Normals ...
                      for (int j = len - 1; j > 0; j--)
                        normals[j] = new DoublePoint(-normals[j - 1].X, -normals[j - 1].Y);
                      
                      normals[0] = new DoublePoint(-normals[1].X, -normals[1].Y);

                      m_k = len - 1;
                      for (m_j = m_k - 1; m_j > 0; --m_j)
                          OffsetPoint(jointype);

                      if (endtype == EndType.etButt)
                      {
                          pt1 = new IntPoint((cInt)Round(pts[m_i][0].X - normals[0].X * delta),
                            (cInt)Round(pts[m_i][0].Y - normals[0].Y * delta));
                          AddPoint(pt1);
                          pt1 = new IntPoint((cInt)Round(pts[m_i][0].X + normals[0].X * delta),
                            (cInt)Round(pts[m_i][0].Y + normals[0].Y * delta));
                          AddPoint(pt1);
                      }
                      else
                      {
                          m_k = 1;
                          m_sinA = 0;
                          if (endtype == EndType.etSquare) 
                            DoSquare();
                          else
                            DoRound();
                      }
                      solution.Add(currentPoly);
                  }
              }

              //finally, clean up untidy corners ...
              Clipper clpr = new Clipper();
              clpr.AddPaths(solution, PolyType.ptSubject, true);
              if (delta > 0)
              {
                  clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
              }
              else
              {
                  IntRect r = clpr.GetBounds();
                  Path outer = new Path(4);

                  outer.Add(new IntPoint(r.left - 10, r.bottom + 10));
                  outer.Add(new IntPoint(r.right + 10, r.bottom + 10));
                  outer.Add(new IntPoint(r.right + 10, r.top - 10));
                  outer.Add(new IntPoint(r.left - 10, r.top - 10));

                  clpr.AddPath(outer, PolyType.ptSubject, true);
                  clpr.ReverseSolution = true;
                  clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative);
                  if (solution.Count > 0) solution.RemoveAt(0);
              }
          }