protected override void SolveInstance(IGH_DataAccess DA) { List <Mesh> bricks = new List <Mesh>(); Point3d center_d = new Point3f(); double mortarth_d = 8; double tolerence_d = 0.1; if (!DA.GetDataList("Bricks", bricks)) { return; } if (!DA.GetData("Center", ref center_d)) { return; } if (!DA.GetData("MortarThickness", ref mortarth_d)) { return; } if (!DA.GetData("zTolerence", ref tolerence_d)) { return; } if (bricks.Count == 0) { return; } if (!bricks[0].IsValid) { return; } if (!center_d.IsValid) { return; } if (tolerence_d <= 0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "zTolerence must be positive"); return; } if (mortarth_d <= 0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "MortarThickness must be positive"); return; } Point3f center = GeometryTools.D2F(center_d); float mortarth = (float)mortarth_d; float tolerence = (float)tolerence_d; List <float> z_list = new List <float>(); List <Plane> planes_list = new List <Plane>(); List <string> types_list = new List <string>(); List <Point3f[]> corners_list = new List <Point3f[]>(); for (int i = 0; i < bricks.Count; i++) { Mesh this_brick = bricks[i]; List <Point3f> vertices = new List <Point3f>(); List <float> zs = new List <float>(); List <Point3f> this_corner = new List <Point3f>(); Plane this_plane = new Plane(); //读取所有顶点,检测是否为8个 vertices = this_brick.Vertices.ToList(); GeometryTools.PurifyPoints(ref vertices, 0.1f); if (vertices.Count != 8) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "For a brick, there must be 8 vertices, now here is" + vertices.Count.ToString()); return; } //将顶点根据高度排序 for (int j = 0; j < vertices.Count; j++) { zs.Add(vertices[j].Z); } if (!DataTools.Sort(ref zs, ref vertices)) { return; } //提取出上顶点并按3241象限顺序排序 for (int j = 4; j < vertices.Count; j++) { this_corner.Add(vertices[j]); } if (!GeometryTools.Sortby3241Q(ref this_corner, center)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Has slanted bricks"); GeometryTools.Sortby3241D(ref this_corner, center); if (GeometryTools.Distance(this_corner[0], this_corner[2]) > GeometryTools.Distance(this_corner[0], this_corner[3])) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Geometric error"); return; } } //检验砖块是否存在几何错误 if (GeometryTools.Distance(this_corner[0], this_corner[2]) > GeometryTools.Distance(this_corner[0], this_corner[3])) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Geometrical Error."); return; } //将砖块类型及放砖坐标系加入列表 if (GeometryTools.Distance(this_corner[0], this_corner[1]) - GeometryTools.Distance(this_corner[0], this_corner[2]) > 50) { types_list.Add("Vertical"); this_plane = new Plane(GeometryTools.Average(this_corner), GeometryTools.P2P(this_corner[0], this_corner[2]), GeometryTools.P2P(this_corner[0], this_corner[1])); } else if (GeometryTools.Distance(this_corner[0], this_corner[2]) - GeometryTools.Distance(this_corner[0], this_corner[1]) > 50) { types_list.Add("Horizontal"); this_plane = new Plane(GeometryTools.Average(this_corner), GeometryTools.P2P(this_corner[0], this_corner[2]), GeometryTools.P2P(this_corner[0], this_corner[1])); } else { types_list.Add("Half"); this_plane = new Plane(GeometryTools.Average(new Point3f[] { this_corner[0], this_corner[1] }), GeometryTools.P2P(this_corner[0], this_corner[2]), GeometryTools.P2P(this_corner[0], this_corner[1])); } planes_list.Add(this_plane); //将坐标系原点高度加入列表 z_list.Add((float)this_plane.Origin.Z); //将上顶点加入列表 corners_list.Add(this_corner.ToArray()); } //将各元素按高度排序 List <float> z_list_copy1 = new List <float>(z_list); List <float> z_list_copy2 = new List <float>(z_list); if (!DataTools.Sort(ref z_list_copy1, ref planes_list)) { return; } if (!DataTools.Sort(ref z_list_copy2, ref types_list)) { return; } if (!DataTools.Sort(ref z_list, ref corners_list)) { return; } DataTree <Plane> planes = new DataTree <Plane>(); DataTree <string> types = new DataTree <string>(); DataTree <Point3f> corners = new DataTree <Point3f>(); int now_floor = 0; float now_z = 0; List <Plane> now_planes = new List <Plane>(); List <string> now_types = new List <string>(); List <Point3f[]> now_corners = new List <Point3f[]>(); GH_Path now_path1 = new GH_Path(); GH_Path now_path2 = new GH_Path(); for (int i = 0; i < z_list.Count; i++) { //常执行 planes_list[i] = GeometryTools.Move(planes_list[i], 0, 0, now_floor * mortarth); for (int j = 0; j < 4; j++) { corners_list[i][j] = GeometryTools.Move(corners_list[i][j], 0, 0, now_floor * mortarth); } //第一个元素 if (i == 0) { now_floor = 0; now_z = z_list[i]; now_planes.Clear(); now_types.Clear(); now_corners.Clear(); now_planes.Add(planes_list[i]); now_types.Add(types_list[i]); now_corners.Add(corners_list[i]); } //最后一个元素 else if (i == z_list.Count - 1) { now_planes.Add(planes_list[i]); now_types.Add(types_list[i]); now_corners.Add(corners_list[i]); List <Plane> now_planes_copy = new List <Plane>(now_planes); GeometryTools.SortbyClock(ref now_planes_copy, ref now_types, center); GeometryTools.SortbyClock(ref now_planes, ref now_corners, center); now_path1 = new GH_Path(); now_path1.FromString("{" + now_floor.ToString() + "}"); planes.AddRange(now_planes, now_path1); types.AddRange(now_types, now_path1); for (int j = 0; j < now_corners.Count; j++) { now_path2 = new GH_Path(); now_path2.FromString("{" + now_floor.ToString() + ";" + j.ToString() + "}"); corners.AddRange(now_corners[j].ToList(), now_path2); } } //没有高度突变 else if (Math.Abs(z_list[i] - now_z) < tolerence) { now_planes.Add(planes_list[i]); now_types.Add(types_list[i]); now_corners.Add(corners_list[i]); } //高度突变 else { List <Plane> now_planes_copy = new List <Plane>(now_planes); GeometryTools.SortbyClock(ref now_planes_copy, ref now_types, center); GeometryTools.SortbyClock(ref now_planes, ref now_corners, center); now_path1 = new GH_Path(); now_path1.FromString("{" + now_floor.ToString() + "}"); planes.AddRange(now_planes, now_path1); types.AddRange(now_types, now_path1); for (int j = 0; j < now_corners.Count; j++) { now_path2 = new GH_Path(); now_path2.FromString("{" + now_floor.ToString() + ";" + j.ToString() + "}"); corners.AddRange(now_corners[j].ToList(), now_path2); } now_planes.Clear(); now_types.Clear(); now_corners.Clear(); planes_list[i] = GeometryTools.Move(planes_list[i], 0, 0, mortarth); for (int j = 0; j < 4; j++) { corners_list[i][j] = GeometryTools.Move(corners_list[i][j], 0, 0, mortarth); } now_planes.Add(planes_list[i]); now_types.Add(types_list[i]); now_corners.Add(corners_list[i]); now_floor++; now_z = z_list[i]; } } DA.SetDataTree(0, planes); DA.SetDataTree(1, types); DA.SetDataTree(2, corners); }
/// <summary> /// 根据一个中心点(3f)顺时针对一组坐标系和一组对应值进行排序,键值顺序改变 /// </summary> /// <param name="planes"></param> /// <param name="center"></param> /// <returns></returns> public static void SortbyClock <T>(ref List <Plane> planes, ref List <T> values, Point3f center) { List <Point3f> origins = new List <Point3f>(); for (int i = 0; i < planes.Count; i++) { origins.Add(D2F(planes[i].Origin)); } Point3f average = Average(origins); Vector3f vector1 = P2P(center, average); List <float>[] distances = new List <float> [5]; List <Plane>[] part_planes = new List <Plane> [5]; List <T>[] part_values = new List <T> [5]; for (int i = 0; i < 5; i++) { distances[i] = new List <float>(); part_planes[i] = new List <Plane>(); part_values[i] = new List <T>(); } for (int i = 0; i < origins.Count; i++) { Vector3f vector2 = P2P(center, origins[i]); int quadrant = Quadrant(vector1, vector2); distances[quadrant].Add(Distance(origins[i], average)); part_planes[quadrant].Add(planes[i]); part_values[quadrant].Add(values[i]); } for (int i = 0; i < 5; i++) { if (distances[i].Count != 0) { List <float> _distance = new List <float>(distances[i]); DataTools.Sort(ref _distance, ref part_planes[i]); DataTools.Sort(ref distances[i], ref part_values[i]); } } part_planes[4].Reverse(); part_values[4].Reverse(); part_planes[2].Reverse(); part_values[2].Reverse(); planes.Clear(); values.Clear(); if (part_planes[3].Count != 0) { planes.AddRange(part_planes[3]); } if (part_planes[2].Count != 0) { planes.AddRange(part_planes[2]); } if (part_planes[1].Count != 0) { planes.AddRange(part_planes[1]); } if (part_planes[4].Count != 0) { planes.AddRange(part_planes[4]); } if (part_values[3].Count != 0) { values.AddRange(part_values[3]); } if (part_values[2].Count != 0) { values.AddRange(part_values[2]); } if (part_values[1].Count != 0) { values.AddRange(part_values[1]); } if (part_values[4].Count != 0) { values.AddRange(part_values[4]); } }
protected override void SolveInstance(IGH_DataAccess DA) { Mesh brick = new Mesh(); Point3d center_d = new Point3f(); GH_Structure <GH_String> raw_types = new GH_Structure <GH_String>(); if (!DA.GetData("Brick", ref brick)) { return; } if (!DA.GetData("Center", ref center_d)) { return; } if (!DA.GetDataTree("Types", out raw_types)) { return; } if (raw_types.DataCount == 0) { return; } if (!raw_types.get_DataItem(0).IsValid) { return; } if (!center_d.IsValid) { return; } if (!DataTools.IsTreeDimension2(raw_types)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Wrong tree structure of types, please use {0}{1} type"); return; } Point3f center = GeometryTools.D2F(center_d); List <List <string> > types = DataTools.TreeToList2(raw_types); List <Point3f> vertices = new List <Point3f>(); List <Line> lines = new List <Line>(); List <float> distances = new List <float>(); List <Point3f> corners = new List <Point3f>(); Point3f corner = new Point3f(); Point3f average = new Point3f(); Point3f average2 = new Point3f(); //读取所有顶点,检测是否为8个 vertices = brick.Vertices.ToList(); GeometryTools.PurifyPoints(ref vertices, 0.1f); if (vertices.Count != 8) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "For a brick, there must be 8 vertices, now here is" + vertices.Count.ToString()); return; } //取出各边,按边长排序 for (int i = 0; i < vertices.Count - 1; i++) { for (int j = i + 1; j < vertices.Count; j++) { lines.Add(new Line(vertices[i], vertices[j])); distances.Add(GeometryTools.Distance(vertices[i], vertices[j])); } } DataTools.Sort(ref distances, ref lines); //取出最短四条边的上顶点 for (int i = 0; i < 4; i++) { Point3f from = GeometryTools.D2F(lines[i].From); Point3f to = GeometryTools.D2F(lines[i].To); float z1 = from.Z; float z2 = to.Z; if (z1 > z2) { corners.Add(from); } else { corners.Add(to); } } //按据角点距离排序顶点 distances.Clear(); for (int i = 0; i < corners.Count; i++) { distances.Add(GeometryTools.Distance(corners[i], center)); } DataTools.Sort(ref distances, ref corners); corner = corners[0]; distances.Clear(); for (int i = 0; i < corners.Count; i++) { distances.Add(GeometryTools.Distance(corners[i], corner)); } DataTools.Sort(ref distances, ref corners); average = GeometryTools.Average(corners); average2 = GeometryTools.Average(new Point3f[] { corners[2], corners[3] }); average2 = GeometryTools.Average(new Point3f[] { average, average2 }); List <List <Plane> > planes_list = new List <List <Plane> >(); //生成抓取坐标系 for (int i = 0; i < types.Count; i++) { planes_list.Add(new List <Plane>()); for (int j = 0; j < types[i].Count; j++) { if (types[i][j] == "Horizontal" || types[i][j] == "Half") { planes_list[i].Add(new Plane(average, GeometryTools.P2P(corners[0], corners[2]), GeometryTools.P2P(corners[0], corners[1]))); } else if (types[i][j] == "Vertical") { planes_list[i].Add(new Plane(average, GeometryTools.P2P(corners[0], corners[1]), GeometryTools.P2P(corners[0], corners[2]))); } else { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Wrong type name"); return; } } } DataTree <Plane> plane = DataTools.ListToTree2(planes_list); Plane home = planes_list[0][0]; home = GeometryTools.Move(home, home.ZAxis * 200); DA.SetDataTree(0, plane); DA.SetData("Home", home); }
protected override void SolveInstance(IGH_DataAccess DA) { GH_Structure <GH_Plane> raw_bricks = new GH_Structure <GH_Plane>(); GH_Structure <GH_String> raw_types = new GH_Structure <GH_String>(); GH_Structure <GH_Point> raw_corners = new GH_Structure <GH_Point>(); Plane suckerCenter = new Plane(); Plane sensorCenter = new Plane(); Plane homePlane = new Plane(); double retreat = 160; if (!DA.GetDataTree("Bricks", out raw_bricks)) { return; } if (!DA.GetDataTree("Types", out raw_types)) { return; } if (!DA.GetDataTree("Corners", out raw_corners)) { return; } if (!DA.GetData("SuckerCenter", ref suckerCenter)) { return; } if (!DA.GetData("SensorCenter", ref sensorCenter)) { return; } if (!DA.GetData("HomePlane", ref homePlane)) { return; } if (!DA.GetData("Retreat", ref retreat)) { return; } if (raw_bricks.DataCount == 0) { return; } if (raw_types.DataCount == 0) { return; } if (raw_corners.DataCount == 0) { return; } if (!raw_bricks.get_DataItem(0).IsValid) { return; } if (!raw_types.get_DataItem(0).IsValid) { return; } if (!raw_corners.get_DataItem(0).IsValid) { return; } if (!DataTools.IsTreeDimension2(raw_bricks)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Wrong tree structure of bricks, please use {0}{1} type"); return; } if (!DataTools.IsTreeDimension2(raw_types)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Wrong tree structure of types, please use {0}{1} type"); return; } if (!DataTools.IsTreeDimension3(raw_corners)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Wrong tree structure of corners, please use {0;0}{0;1} type"); return; } if (!DataTools.IsTreeMatch23(raw_bricks, raw_corners)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Bricks and corners does not match"); return; } if (!DataTools.IsTreeMatch23(raw_types, raw_corners)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Types and corners does not match"); return; } if (retreat < 0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Retreat must not be negative"); return; } List <List <Plane> > bricks = DataTools.TreeToList2(raw_bricks); List <List <string> > types = DataTools.TreeToList2(raw_types); List <List <List <Point3d> > > corners = DataTools.TreeToList3(raw_corners); List <List <Plane> > targets_list = new List <List <Plane> >(); List <List <string> > names_list = new List <List <string> >(); string[] title = { "Floor", "Middle", "Brick", "Sensor" }; for (int i = 0; i < bricks.Count - 1; i++) { targets_list.Add(new List <Plane>()); names_list.Add(new List <string>()); targets_list[i].Add(GeometryTools.Move(homePlane, new Vector3d(0, 0, (bricks[i][0].OriginZ - bricks[0][0].OriginZ) * 0.8))); names_list[i].Add(title[0] + i.ToString() + title[1] + "0"); for (int j = 0; j < bricks[i].Count; j++) { Point3d[] now_points = new Point3d[4]; Point3d[] this_corners = corners[i][j].ToArray(); Point3d this_center = GeometryTools.Average(this_corners); if (types[i][j] == "Horizontal" || types[i][j] == "Half") { now_points[0] = GeometryTools.Average(this_center, this_corners[0]); now_points[1] = GeometryTools.Average(this_center, this_corners[1]); now_points[2] = GeometryTools.Average(this_center, this_corners[3]); now_points[3] = GeometryTools.Average(this_center, this_corners[2]); } else if (types[i][j] == "Vertical") { now_points[0] = GeometryTools.Average(this_center, this_corners[1]); now_points[1] = GeometryTools.Average(this_center, this_corners[3]); now_points[2] = GeometryTools.Average(this_center, this_corners[2]); now_points[3] = GeometryTools.Average(this_center, this_corners[0]); } for (int k = 0; k < now_points.Count(); k++) { Plane now_plane = GeometryTools.Move(bricks[i][j], GeometryTools.P2P(bricks[i][j].Origin, now_points[k])); now_plane = GeometryTools.Move(now_plane, 0, 0, retreat - 50); now_plane = GeometryTools.Transform(sensorCenter, suckerCenter, now_plane); targets_list[i].Add(now_plane); names_list[i].Add(title[0] + i.ToString() + title[2] + j.ToString() + title[3] + k.ToString()); } } targets_list[i].Add(GeometryTools.Move(homePlane, new Vector3d(0, 0, (bricks[i][0].OriginZ - bricks[0][0].OriginZ) * 0.8))); names_list[i].Add(title[0] + i.ToString() + title[1] + "1"); } DataTree <Plane> targets = DataTools.ListToTree2(targets_list); DataTree <string> names = DataTools.ListToTree2(names_list); DA.SetDataTree(0, targets); DA.SetDataTree(1, names); }
protected override void SolveInstance(IGH_DataAccess DA) { GH_Structure <GH_Plane> raw_bricks = new GH_Structure <GH_Plane>(); GH_Structure <GH_String> raw_types = new GH_Structure <GH_String>(); GH_Structure <GH_Point> raw_corners = new GH_Structure <GH_Point>(); Plane suckerCenter = new Plane(); Plane nozzleCenter = new Plane(); Plane homePlane = new Plane(); double horizontalBorder = 25; double verticalBorder = 25; double gap = 25; double retreat = 10; if (!DA.GetDataTree("Bricks", out raw_bricks)) { return; } if (!DA.GetDataTree("Types", out raw_types)) { return; } if (!DA.GetDataTree("Corners", out raw_corners)) { return; } if (!DA.GetData("SuckerCenter", ref suckerCenter)) { return; } if (!DA.GetData("NozzleCenter", ref nozzleCenter)) { return; } if (!DA.GetData("HomePlane", ref homePlane)) { return; } if (!DA.GetData("HorizontalBorder", ref horizontalBorder)) { return; } if (!DA.GetData("VerticalBorder", ref verticalBorder)) { return; } if (!DA.GetData("Gap", ref gap)) { return; } if (!DA.GetData("Retreat", ref retreat)) { return; } if (raw_bricks.DataCount == 0) { return; } if (raw_types.DataCount == 0) { return; } if (raw_corners.DataCount == 0) { return; } if (!raw_bricks.get_DataItem(0).IsValid) { return; } if (!raw_types.get_DataItem(0).IsValid) { return; } if (!raw_corners.get_DataItem(0).IsValid) { return; } if (!DataTools.IsTreeDimension2(raw_bricks)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Wrong tree structure of bricks, please use {0}{1} type"); return; } if (!DataTools.IsTreeDimension2(raw_types)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Wrong tree structure of types, please use {0}{1} type"); return; } if (!DataTools.IsTreeDimension3(raw_corners)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Wrong tree structure of corners, please use {0;0}{0;1} type"); return; } if (!DataTools.IsTreeMatch23(raw_bricks, raw_corners)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Bricks and corners does not match"); return; } if (!DataTools.IsTreeMatch23(raw_types, raw_corners)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Types and corners does not match"); return; } if (horizontalBorder < 0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Horizontal border must not be negative"); return; } if (verticalBorder < 0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Vertical border must not be negative"); return; } if (gap <= 0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Gap must be positive"); return; } if (retreat < 0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Retreat must not be negative"); return; } List <List <Plane> > bricks = DataTools.TreeToList2(raw_bricks); List <List <string> > types = DataTools.TreeToList2(raw_types); List <List <List <Point3d> > > corners = DataTools.TreeToList3(raw_corners); List <List <Plane> > targets_list = new List <List <Plane> >(); List <List <string> > names_list = new List <List <string> >(); string[] title = { "Floor", "Target" }; for (int i = 0; i < bricks.Count - 1; i++) { targets_list.Add(new List <Plane>()); names_list.Add(new List <string>()); int count = 0; targets_list[i].Add(GeometryTools.Move(homePlane, new Vector3d(0, 0, (bricks[i][0].OriginZ - bricks[0][0].OriginZ) * 0.8))); names_list[i].Add(title[0] + i.ToString() + title[1] + count.ToString()); for (int j = 0; j < bricks[i].Count; j++) { List <Plane> now_planes = new List <Plane>(); Point3d[] sorted_corners = new Point3d[4]; Point3d[] this_corners = corners[i][j].ToArray(); if (types[i][j] == "Horizontal" || types[i][j] == "Half") { sorted_corners = this_corners; now_planes = GeometryTools.Hatch(bricks[i][j], sorted_corners, horizontalBorder, verticalBorder, gap); } else if (types[i][j] == "Vertical") { sorted_corners[0] = this_corners[1]; sorted_corners[1] = this_corners[3]; sorted_corners[2] = this_corners[0]; sorted_corners[3] = this_corners[2]; now_planes = GeometryTools.Hatch(bricks[i][j], sorted_corners, verticalBorder, horizontalBorder, gap); } else { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Wrong type name"); return; } for (int k = 0; k < now_planes.Count; k++) { now_planes[k] = GeometryTools.Move(now_planes[k], 0, 0, retreat); now_planes[k] = GeometryTools.Transform(nozzleCenter, suckerCenter, now_planes[k]); if (j == 0 && k == 0) { count++; targets_list[i].Add(GeometryTools.Move(now_planes[k], -bricks[i][j].XAxis * 150)); names_list[i].Add(title[0] + i.ToString() + title[1] + count.ToString()); } count++; targets_list[i].Add(now_planes[k]); names_list[i].Add(title[0] + i.ToString() + title[1] + count.ToString()); if (j == bricks[i].Count - 1 && k == now_planes.Count - 1) { count++; targets_list[i].Add(GeometryTools.Move(now_planes[k], bricks[i][j].XAxis * 150)); names_list[i].Add(title[0] + i.ToString() + title[1] + count.ToString()); } } } count++; targets_list[i].Add(GeometryTools.Move(homePlane, new Vector3d(0, 0, (bricks[i][0].OriginZ - bricks[0][0].OriginZ) * 0.8))); names_list[i].Add(title[0] + i.ToString() + title[1] + count.ToString()); } DataTree <Plane> targets = DataTools.ListToTree2(targets_list); DataTree <string> names = DataTools.ListToTree2(names_list); DA.SetDataTree(0, targets); DA.SetDataTree(1, names); }