Ejemplo n.º 1
0
        public void GenegateUnigineSpline()
        {
            Document adoc = Application.DocumentManager.MdiActiveDocument;

            if (adoc == null)
            {
                return;
            }

            Database db = adoc.Database;

            Editor ed = adoc.Editor;

            try
            {
                //выбрать 3d полилинию
                PromptEntityOptions peo1 = new PromptEntityOptions("\nВыберите 3D полилинию");
                peo1.SetRejectMessage("\nМожно выбрать только 3D полилинию");
                peo1.AddAllowedClass(typeof(Polyline3d), true);
                PromptEntityResult per1 = ed.GetEntity(peo1);
                if (per1.Status != PromptStatus.OK)
                {
                    return;
                }

                //создание данных для сериализации
                UnigineSpline unigineSpline = new UnigineSpline();
                Point3d       center        = Point3d.Origin;
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    Polyline3d poly = tr.GetObject(per1.ObjectId, OpenMode.ForRead) as Polyline3d;
                    if (poly == null)
                    {
                        return;
                    }

                    ObjectId[] verts = poly.Cast <ObjectId>().ToArray();

                    List <Point3d> pts = new List <Point3d>(verts.Length);
                    for (int i = 0; i < verts.Length; i++)
                    {
                        PolylineVertex3d vt      = tr.GetObject(verts[i], OpenMode.ForRead) as PolylineVertex3d;
                        Point3d          point3d = vt.Position;
                        pts.Add(point3d);
                    }

                    //найти среднюю точку
                    foreach (Point3d pt in pts)
                    {
                        center = center.Add(new Vector3d(pt.X, pt.Y, pt.Z));
                    }
                    center = center.DivideBy(pts.Count);

                    for (int i = 0; i < pts.Count; i++)
                    {
                        pts[i] = pts[i].Subtract(new Vector3d(center.X, center.Y, center.Z));
                    }


                    List <Vector3d> tangents = new List <Vector3d>(verts.Length);
                    tangents.Add((pts[1] - pts[0]).GetNormal());
                    for (int i = 1; i < verts.Length - 1; i++)
                    {
                        Vector3d tangent = ((pts[i + 1] - pts[i]).GetNormal()
                                            + (pts[i] - pts[i - 1]).GetNormal()).GetNormal();
                        tangents.Add(tangent);
                    }
                    tangents.Add((pts[verts.Length - 1] - pts[verts.Length - 2]).GetNormal());

                    for (int i = 0; i < verts.Length; i++)
                    {
                        unigineSpline.points.Add(new double[] { pts[i].X, pts[i].Y, pts[i].Z });

                        if (i > 0)
                        {
                            //тангенсы должны быть по модулю примерно 1/4 от расстояния между точками
                            double   mult = (pts[i] - pts[i - 1]).Length / 4;
                            Vector3d tan0 = tangents[i - 1] * mult;
                            Vector3d tan1 = -tangents[i] * mult;

                            //сегмент
                            UnigineSegment segment = new UnigineSegment()
                            {
                                start_index   = i - 1,
                                start_tangent = new double[] { tan0.X, tan0.Y, tan0.Z },
                                start_up      = new double[] { 0, 0, 1 },
                                end_index     = i,
                                end_tangent   = new double[] { tan1.X, tan1.Y, tan1.Z },
                                end_up        = new double[] { 0, 0, 1 },
                            };
                            unigineSpline.segments.Add(segment);
                        }
                    }

                    if (poly.Closed || pts[0].IsEqualTo(pts[verts.Length - 1]))
                    {
                        UnigineSegment lastSeg  = unigineSpline.segments.Last();
                        UnigineSegment firstSeg = unigineSpline.segments.First();

                        if (pts[0].IsEqualTo(pts[verts.Length - 1]))
                        {
                            //замыкающий сегмент привязывается к стартовой точке

                            lastSeg.end_index = 0;

                            //тангенсы в стартовой точке
                            Vector3d tan = ((pts[1] - pts[0]).GetNormal()
                                            + (pts[verts.Length - 1] - pts[verts.Length - 2]).GetNormal()).GetNormal();
                            Vector3d tanLast = -tan * (pts[lastSeg.end_index] - pts[lastSeg.start_index]).Length / 4;
                            lastSeg.end_tangent = new double[] { tanLast.X, tanLast.Y, tanLast.Z };


                            Vector3d tanFirst = tan * (pts[firstSeg.end_index] - pts[firstSeg.start_index]).Length / 4;
                            firstSeg.start_tangent = new double[] { tanFirst.X, tanFirst.Y, tanFirst.Z };
                        }
                        else
                        {
                            //тангенсы в стартовой и последней точке
                            Point3d  lastPt   = pts[verts.Length - 1];
                            Point3d  firstPt  = pts[0];
                            Vector3d tanStart = ((pts[1] - firstPt).GetNormal()
                                                 + (firstPt - lastPt).GetNormal()).GetNormal();
                            Vector3d tanEnd = ((firstPt - lastPt).GetNormal()
                                               + (lastPt - pts[verts.Length - 2]).GetNormal()).GetNormal();

                            Vector3d tanLast = -tanEnd * (pts[lastSeg.end_index] - pts[lastSeg.start_index]).Length / 4;
                            lastSeg.end_tangent = new double[] { tanLast.X, tanLast.Y, tanLast.Z };

                            Vector3d tanFirst = tanStart * (pts[firstSeg.end_index] - pts[firstSeg.start_index]).Length / 4;
                            firstSeg.start_tangent = new double[] { tanFirst.X, tanFirst.Y, tanFirst.Z };

                            //замыкающий сегмент
                            double   mult = (firstPt - lastPt).Length / 4;
                            Vector3d tan0 = tanEnd * mult;
                            Vector3d tan1 = -tanStart * mult;

                            UnigineSegment segment = new UnigineSegment()
                            {
                                start_index   = verts.Length - 1,
                                start_tangent = new double[] { tan0.X, tan0.Y, tan0.Z },
                                start_up      = new double[] { 0, 0, 1 },
                                end_index     = 0,
                                end_tangent   = new double[] { tan1.X, tan1.Y, tan1.Z },
                                end_up        = new double[] { 0, 0, 1 },
                            };
                            unigineSpline.segments.Add(segment);
                        }
                    }


                    tr.Commit();
                }


                //сериализация
                //TODO: Сделать выбор папки
                if (unigineSpline.segments.Count > 0)
                {
                    string fileName = Common.Utils.GetNonExistentFileName(Path.GetDirectoryName(adoc.Name),
                                                                          center.ToString().Replace(',', '_').Substring(1, center.ToString().Length - 2), "spl");
                    using (StreamWriter file = System.IO.File.CreateText(fileName))
                    {
                        JsonSerializer serializer = new JsonSerializer();
                        serializer.Serialize(file, unigineSpline);
                    }
                }
            }
            catch (System.Exception ex)
            {
                CommonException(ex, "Ошибка при создании сплайна для UNIGINE");
            }
        }