/// <summary> /// 图形的扩张与收缩,存在BUG,需要再处理 /// </summary> /// <param name="lines"></param> /// <returns></returns> public List <Line3D> Elastic(List <Line3D> lines, double range, List <Line3D> neverOffset) { List <Line3D> NLList = new List <Line3D>(); //获取当前线段的顺时针排序 List <Line3D> sortLines = GraphicAlgorithm.Sort(lines); //获取当前连续的顶点 List <Vector3D> PList = new List <Vector3D>(); //当前直线的方向 List <Vector3D> DList = new List <Vector3D>(); //记录所有的点 sortLines.ForEach(x => { PList.Add(x.Start); DList.Add(x.Direction); }); //所有点的列表 List <Vector3D> NPList = new List <Vector3D>(); int startIndex, endindex; //获取所有的点 for (int i = 0; i < DList.Count; i++) { startIndex = i == 0 ? DList.Count - 1 : i - 1; endindex = i; //两个线之间的夹角 double sina = DList[startIndex].Cross(DList[endindex]).Modulus(); //由于偏移出是平行四边形,则要移动的长度为 var moveLen = -range / sina; //移动的方向为 var movedir = DList[endindex] - DList[startIndex]; Vector3D np = DList[i] + movedir * moveLen; //添加新点 NPList.Add(np); } ///形成新的线 for (int i = 0; i < NPList.Count; i++) { var index = i == (DList.Count - 1) ? 0 : i + 1; NLList.Add(Line3D.Create(NPList[i], NPList[index])); } return(NLList); }
/// <summary> /// 按照指定的高度和宽度,对规则矩形进行划分,当前算法,运行的前提条件是,传入的图形是矩形元素 /// </summary> /// <param name="square"></param> /// <param name="width"></param> /// <param name="height"></param> /// <returns></returns> public List <List <Line2D> > Partition(List <Line2D> square, double width, double height, Vector2D offset) { //根据板子宽度和高度,重新定义偏移量 var loffset = this.LayoutOffset(width, height, offset); //获取要划分的矩形裕兴 List <Line2D> lines = new List <Line2D>(square); //获取当前的划分多边形 List <List <Line2D> > result = new List <List <Line2D> >(); //获取图形中的最小点 List <Vector2D> vst = new List <Vector2D>(); square.ForEach(x => { vst.Add(x.Start); vst.Add(x.End); }); //排除相同点 vst = vst.Distinct(new Vector2DEqualityComparer()).ToList(); //查找最小角点 var origin = vst.OrderBy(a => { return(Math.Round(a.X, 7)); }).ThenBy(b => { return(Math.Round(b.Y, 7)); }).FirstOrDefault(); ////查找最小角点 //var origin = vst.OrderBy(a => a.X).ThenBy(c => c.Y).FirstOrDefault(); //逆时针排序,排列出 List <Line2D> sequeeLines = GraphicAlgorithm.Sort(lines, origin, 1); //获取当前矩形的实际宽度和高度 double sw = sequeeLines[0].Length + loffset.X; double sh = sequeeLines[1].Length + loffset.Y; //代表需要水平偏移的个数 var lnx = Math.Ceiling(sw / width); //代表垂直偏移的个数 var lny = Math.Ceiling(sh / height); for (int i = 0; i < lnx; i++) { for (int j = 0; j < lny; j++) { Vector2D startPoint = null; if (loffset != null) { startPoint = origin - loffset; } //代表顶点的偏移 Vector2D v1 = startPoint.Offset(width * i * sequeeLines[0].Direction).Offset(height * j * sequeeLines[1].Direction); //最右边的顶点偏移 Vector2D v2 = startPoint.Offset(width * (i + 1) * sequeeLines[0].Direction).Offset(height * j * sequeeLines[1].Direction); //偏移Y方向的区域,假如超过边界,则取边界值 Vector2D v4 = startPoint.Offset(width * i * sequeeLines[0].Direction).Offset(height * (j + 1) * sequeeLines[1].Direction); if (v1.X < origin.X) { v1.X = origin.X; } if (v1.Y < origin.Y) { v1.Y = origin.Y; } //假如超出边界,则取边界值 if (v2.X > (origin.X + sequeeLines[0].Length)) { v2 = Vector2D.Create(origin.X + sequeeLines[0].Length, v2.Y); } if (v2.Y < origin.Y) { v2.Y = origin.Y; } if (v4.Y > (origin.Y + sequeeLines[1].Length)) { v4 = Vector2D.Create(v1.X, origin.Y + sequeeLines[1].Length); } if (v4.X < origin.X) { v4.X = origin.X; } if (v4.Y < origin.Y) { v4.Y = origin.Y; } //计算对角点 Vector2D v3 = Vector2D.Create(v2.X, v4.Y); //获取划分的小多边形 List <Line2D> line2ds = new List <Line2D>() { Line2D.Create(v1, v2), Line2D.Create(v2, v3), Line2D.Create(v3, v4), Line2D.Create(v4, v1) }; result.Add(line2ds); } } return(result); }
/// <summary> /// 对多边形进行扩张和缩放,range为负数为内缩小,为正数为外扩 /// </summary> /// <param name="lines"></param> /// <param name="range"></param> /// <returns></returns> public List <Line2D> Elastic(List <Line2D> lines, double range, List <Line2D> neverOffset, bool allowDistortion = false) { if (range < 0) { //说明会引起多边形形状的变化 Line2D line = lines.Find(x => x.Length < Math.Abs(range)); //说明图形已经边型了,需要变形处理 if (line != null && allowDistortion) { //允许变形的缩放 this.ElasticDistortion(lines, range); } } List <Line2D> NLList = new List <Line2D>(); //首先需要对线段进行一次合并,由于多边形可能存在共线的情况,那么偏移会出问题 var mergelines = GraphicAlgorithm.Merge(lines); //获取当前线段的顺时针排序 List <Line2D> sortLines = GraphicAlgorithm.Sort(mergelines, null, 1); //获取当前连续的顶点 List <Vector2D> PList = new List <Vector2D>(); //当前直线的方向 List <Vector2D> DList = new List <Vector2D>(); //记录所有的点 sortLines.ForEach(x => { PList.Add(x.Start); DList.Add(x.Direction); }); //所有点的列表 List <Vector2D> NPList = new List <Vector2D>(); int startIndex, endindex; //获取所有的点 for (int i = 0; i < DList.Count; i++) { startIndex = i == 0 ? DList.Count - 1 : i - 1; endindex = i; //两个线之间的夹角 double sina = DList[startIndex].Cross(DList[endindex]); //用于判断当前是阴阳角 var Corndir = 0; if (sina > 0) { Corndir = 1; } else { Corndir = -1; } //由于偏移出是平行四边形,则要移动的长度为 var moveLen = -range / sina; Vector2D movedir = null; if (neverOffset != null) { var nf = neverOffset.FindAll(x => x.Start.IsAlmostEqualTo(PList[i]) || x.End.IsAlmostEqualTo(PList[i])); if (nf != null && nf.Count == 1) { if (nf[0].Direction.IsAlmostEqualTo(DList[startIndex]) || nf[0].Direction.IsAlmostEqualTo(-DList[startIndex])) { movedir = DList[startIndex]; Vector2D npt = PList[i] + movedir * range * Corndir; NPList.Add(npt); } else { movedir = -DList[endindex]; Vector2D npt = PList[i] + movedir * range * Corndir; NPList.Add(npt); } continue; } if (nf != null && nf.Count == 2) { NPList.Add(PList[i]); continue; } } //移动的方向为 movedir = DList[endindex] - DList[startIndex]; Vector2D np = PList[i] + movedir * moveLen; //添加新点 NPList.Add(np); } ///形成新的线 for (int i = 0; i < NPList.Count; i++) { var index = i == (NPList.Count - 1) ? 0 : i + 1; NLList.Add(Line2D.Create(NPList[i], NPList[index])); } return(NLList); }
/// <summary> /// 对指定的进行每个线段进行缩放,并且指定缩放的长度,传入的线,不能共线或者重叠,否则会出现错误 /// </summary> /// <param name="nlist"></param> /// <returns></returns> public List <Line2D> Elastic2(List <Tuple <Line2D, Double> > nlist) { List <Line2D> lines = new List <Line2D>(); //不处理变形的情况 foreach (var tp in nlist) { if (tp.Item1.Length < tp.Item2) { return(null); } else { lines.Add(tp.Item1); } } //获取当前线段的顺时针排序 List <Line2D> sortLines = GraphicAlgorithm.Sort(lines, null, 1); List <Line2D> moveLines = new List <Line2D>(); ///开始线段偏移 for (int i = 0; i < sortLines.Count; i++) { var v1 = Vector3D.Create(sortLines[i].Start.X, sortLines[i].Start.Y, 0); var v2 = Vector3D.Create(sortLines[i].End.X, sortLines[i].End.Y, 0); var l1 = Line3D.Create(v1, v2); var moveDir = l1.Direction.Cross(Vector3D.BasisZ); var tp = nlist.Find(x => x.Item1.IsAlmostEqualTo(sortLines[i])); var nl = l1.Offset(tp.Item2, -moveDir); moveLines.Add(TransformUtil.Projection(nl)); } List <Vector2D> NPList = new List <Vector2D>(); //开始循环所有的线段 for (int i = 0; i < moveLines.Count; i++) { Vector2D v = null; if (i == 0) { v = moveLines[0].IntersectStraightLine(moveLines[moveLines.Count - 1]); } else { v = moveLines[i].IntersectStraightLine(moveLines[i - 1]); } if (v == null) { return(null); } else { NPList.Add(v); } } List <Line2D> nliset = new List <Line2D>(); //生成新的多边形 for (int i = 0; i < NPList.Count; i++) { if (i == 0) { nliset.Add(Line2D.Create(NPList[NPList.Count - 1], NPList[i])); } else { nliset.Add(Line2D.Create(NPList[i - 1], NPList[i])); } } return(nliset); }