예제 #1
0
    void Start()
    {
        WallManager.Instance.Register(this);

        var localToWorld = transform.localToWorldMatrix;
        var mesh         = GetComponent <MeshFilter>().mesh;

        Vector3[] vertices  = mesh.vertices;
        var       triangles = mesh.triangles;

        //找到贴紧地面的那些三角形
        for (int i = 0; i < triangles.Length; i += 3)
        {
            var v0 = localToWorld.MultiplyPoint(vertices[triangles[i]]);
            var v1 = localToWorld.MultiplyPoint(vertices[triangles[i + 1]]);
            var v2 = localToWorld.MultiplyPoint(vertices[triangles[i + 2]]);

            if (Mathf.Abs(v0.y) < k_epsilon && Mathf.Abs(v1.y) < k_epsilon && Mathf.Abs(v2.y) < k_epsilon)
            {
                var list = new List <IntPoint>();
                m_polygons.Add(list);
                list.Add(ClipperUtils.Convert(v0));
                list.Add(ClipperUtils.Convert(v1));
                list.Add(ClipperUtils.Convert(v2));
            }
        }

        //去掉重复的顶点
        m_polygons = Clipper.SimplifyPolygons(m_polygons);
    }
예제 #2
0
    /// <summary>
    /// 生成轮廓线
    /// </summary>
    private void MakeContourLine(List <IntPoint> polygon, Vector2 hitPos)
    {
        //调整起点
        var     list = ClipperUtils.Convert(polygon, k_altitude);
        Vector2 minIntersect;
        int     minIndex;

        FindStartPos(list, hitPos, out minIndex, out minIntersect);

        m_contour = new Vector3[list.Length + 2];
        int index = 0;

        m_contour[index++] = new Vector3(minIntersect.x, k_altitude, minIntersect.y);
        for (int i = minIndex; i < list.Length; i++)
        {
            m_contour[index++] = list[i];
        }
        for (int i = 0; i < minIndex; i++)
        {
            m_contour[index++] = list[i];
        }
        m_contour[index++] = m_contour[0];         //首尾相连

        //设置LineRenderer
        var line = Instantiate(m_contourLine);

        line.transform.SetParent(transform);
        line.transform.position = Vector3.zero;
        line.positionCount      = m_contour.Length;
        line.SetPositions(m_contour);
    }
예제 #3
0
    public List <IntPoint> AroundWall(Vector2 containPoint, float offset)
    {
        //将相邻的障碍物轮廓合并在一起
        List <List <IntPoint> > unions = new List <List <IntPoint> >();
        Clipper clipper = new Clipper();

        for (int i = 0; i < m_walls.Count; i++)
        {
            clipper.AddPolygons(m_walls[i].m_polygons, PolyType.ptSubject);
        }

        if (!clipper.Execute(ClipType.ctUnion, unions))
        {
            Debug.LogError("无法合并顶点");
            return(null);
        }

        //过滤出特定的那个轮廓
        List <IntPoint> contour = null;

        for (int i = 0; i < unions.Count; i++)
        {
            if (ClipperUtils.IsPointOnPolygonEdge(containPoint, unions[i]))
            {
                contour = unions[i];
                break;
            }
        }
        if (contour == null)
        {
            Debug.LogError("没找到包含特定点的障碍轮廓");
            return(null);
        }

        //对轮廓进行偏移
        List <List <IntPoint> > result = new List <List <IntPoint> >()
        {
            contour
        };

        result = Clipper.OffsetPolygons(result, offset * ClipperUtils.k_precision);
        if (result.Count > 1)
        {
            Debug.LogError("轮廓偏移后产生多个轮廓了?");
            return(result[0]);
        }
        else if (result.Count == 0)
        {
            Debug.LogError("轮廓偏移后不产生轮廓了?");
            return(null);
        }
        else
        {
            return(result[0]);
        }
    }
예제 #4
0
        private static void CreateApartments(InDoorGeneratorSettings settings, Floor floor,
                                             List <IntPoint> footprint, List <List <IntPoint> > transitArea, List <Wall> connected)
        {
            var extrudedPolygons = new List <List <IntPoint> >(4);

            settings.Clipper.AddPaths(transitArea, PolyType.ptClip, true);
            settings.Clipper.AddPath(footprint, PolyType.ptSubject, true);
            settings.Clipper.Execute(ClipType.ctDifference, extrudedPolygons);
            settings.Clipper.Clear();

            //SVGBuilder.SaveToFile(extrudedPolygons, "regions_ex.svg", 0.01, 100);

            foreach (var extrudedPolygon in extrudedPolygons)
            {
                // Clipper may produce small polygons on building offsets
                if (Clipper.Area(extrudedPolygon) / DoubleScale < settings.MinimalArea)
                {
                    continue;
                }

                var    firstOuterWallIndex   = InvalidIndex;
                var    firstTransitWallIndex = InvalidIndex;
                var    outerWallCount        = 0;
                double outerWallLength       = 0;
                var    extrudedWalls         = new List <Wall>();
                var    lastItemIndex         = extrudedPolygon.Count - 1;

                var    mergePoint      = Vector2d.Empty;
                double skippedDistance = 0;
                for (var i = 0; i <= lastItemIndex; i++)
                {
                    var start = extrudedPolygon[i];
                    var end   = extrudedPolygon[i == lastItemIndex ? 0 : i + 1];

                    var isOuterWall = ClipperUtils.CalcMinDistance(start, footprint) < IntPrecisionError &&
                                      ClipperUtils.CalcMinDistance(end, footprint) < IntPrecisionError;
                    var p1 = new Vector2d(start.X / Scale, start.Y / Scale);
                    var p2 = new Vector2d(end.X / Scale, end.Y / Scale);

                    // NOTE this allows to skip artifacts of clipper offset library
                    // which I don't know to avoid by clipper API.
                    var distance = p1.DistanceTo(p2);
                    if (distance < settings.HalfTransitAreaWidth &&
                        skippedDistance < settings.TransitAreaWidth)
                    {
                        skippedDistance += distance;
                        if (mergePoint != Vector2d.Empty)
                        {
                            continue;
                        }
                        mergePoint = p1;
                        continue;
                    }
                    if (mergePoint != Vector2d.Empty)
                    {
                        p1              = mergePoint;
                        mergePoint      = Vector2d.Empty;
                        skippedDistance = 0;
                    }

                    if (isOuterWall)
                    {
                        outerWallCount++;
                        outerWallLength += ClipperUtils.Distance(start, end) / Scale;
                        if (firstOuterWallIndex == InvalidIndex)
                        {
                            firstOuterWallIndex = extrudedWalls.Count;
                        }
                    }

                    if (!isOuterWall && firstTransitWallIndex == InvalidIndex)
                    {
                        firstTransitWallIndex = extrudedWalls.Count;
                    }

                    extrudedWalls.Add(new Wall(p1, p2, isOuterWall));
                }

                firstOuterWallIndex = firstOuterWallIndex != 0
                    ? firstOuterWallIndex
                    : firstTransitWallIndex + extrudedWalls.Count - outerWallCount;

                var context = new FloorContext(outerWallCount, extrudedWalls.Count - outerWallCount,
                                               firstOuterWallIndex, firstTransitWallIndex);
                CreateAparments(settings, floor, context, extrudedWalls, connected, outerWallLength);
            }
        }