Beispiel #1
0
        // Create the cap of primitive
        Polygon CreateCap(bool isLower)
        {
            Point3D[] centers = Centers;
            Vector3D[] horizontalVectors = HorizontalVectors;
            Vector3D[] verticalVectors = VerticalVectors;
            double halfWidth = 0.5 * Width;
            double halfHeight = 0.5 * Height;

            // Check the data of primitives
            if (!Tube.IsValid(centers, horizontalVectors, verticalVectors, halfWidth, halfHeight))
                return null;

            // Create the cap
            int index = isLower ? 0 : centers.Length - 1;
            Point3D center = centers[index];
            Vector3D horizontalVector = halfWidth * horizontalVectors[index];
            Vector3D verticalVector = halfHeight * verticalVectors[index];

            // Calculate positions
            Point3D[] positions = new Point3D[Tube.RadialSegementCount];
            for (int i = 0; i < Tube.RadialSegementCount; i++)
            {
                double angle = i * 2 * Math.PI / Tube.RadialSegementCount;
                positions[i] = center + Math.Cos(angle) * horizontalVector + Math.Sin(angle) * verticalVector;
            }

            // Reverse points for upper cap
            if (!isLower) Array.Reverse(positions);

            Polygon result = new Polygon();
            result.Positions = positions;
            // Set the same material
            result.Material = Material;
            return result;
        }
        void UpdateShadow()
        {
            if (substance == null) return;
            if (style == null) return;

            Thread.Sleep(300);

            // Black material
            DiffuseMaterial material = new DiffuseMaterial(Brushes.Black);
            material.Freeze();

            // Create molecules
            ModelVisual3D container = new ModelVisual3D();
            foreach (Data.Molecule molecule in substance.Molecules)
            {
                foreach (Data.Atom atom in molecule.Atoms)
                {
                    if (style.ColorStyle.ColorScheme[atom.Element].Diffuse.A < 5) continue;
                    Sphere sphere = new Sphere();
                    sphere.Material = material;
                    sphere.Radius = Atom.GetAtomRadius(atom, style.GeometryStyle);
                    sphere.Center = atom.Position;
                    container.Children.Add(sphere);
                }
                double bondRadius = Bond.GetBondRadius(style.GeometryStyle);
                foreach (Data.Bond bond in molecule.Bonds)
                {
                    if (style.ColorStyle.UseSingleBondMaterial)
                    {
                        if (style.ColorStyle.BondMaterial.Diffuse.A < 5) continue;
                    }
                    else if (style.ColorStyle.ColorScheme[bond.Begin.Element].Diffuse.A < 5 ||
                             style.ColorStyle.ColorScheme[bond.End.Element].Diffuse.A < 5) continue;
                    Cylinder cylinder = new Cylinder(bond.Begin.Position, bond.End.Position, bondRadius);
                    cylinder.Material = material;
                    container.Children.Add(cylinder);
                }

                #region Build approximation of ribbon

                double radius = 0.45;
                foreach (Data.Chain chain in molecule.Chains)
                {
                    for (int i = 0; i < chain.Residues.Count; i++)
                    {
                        if (chain.Residues[i].GetStructureType() == SecondaryStructureType.Helix)
                           if (style.GeometryStyle.HelixHeight < 0.05 || style.GeometryStyle.HelixWidth < 0.05) continue;
                           else radius = Residue.HelixWidth * ((style.GeometryStyle.HelixHeight + style.GeometryStyle.HelixWidth) / 2.0);
                        if (chain.Residues[i].GetStructureType() == SecondaryStructureType.Sheet)
                           if (style.GeometryStyle.SheetHeight < 0.05 || style.GeometryStyle.SheetWidth < 0.05) continue;
                           else radius = Residue.SheetWidth * ((style.GeometryStyle.SheetHeight + style.GeometryStyle.SheetWidth) / 2.0);
                        if (chain.Residues[i].GetStructureType() == SecondaryStructureType.NotDefined)
                           if (style.GeometryStyle.TurnHeight < 0.05 || style.GeometryStyle.TurnWidth < 0.05) continue;
                           else radius = Residue.TurnWidth * ((style.GeometryStyle.TurnHeight + style.GeometryStyle.TurnWidth) / 2.0);

                        if (chain.Residues[i].GetStructureType() == SecondaryStructureType.Helix && style.ColorStyle.HelixMaterial.Diffuse.A < 5) continue;
                        if (chain.Residues[i].GetStructureType() == SecondaryStructureType.Sheet && style.ColorStyle.SheetMaterial.Diffuse.A < 5) continue;
                        if (chain.Residues[i].GetStructureType() == SecondaryStructureType.NotDefined && style.ColorStyle.TurnMaterial.Diffuse.A < 5) continue;

                        Data.Atom alfaCarbon = chain.Residues[i].AlfaCarbon;
                        if (alfaCarbon != null)
                        {
                            Point3D begin = alfaCarbon.Position;
                            alfaCarbon = null;
                            for (int j = i + 1; j < chain.Residues.Count; j++)
                            {
                                alfaCarbon = chain.Residues[j].AlfaCarbon;
                                if (alfaCarbon != null) break;
                            }
                            if (alfaCarbon != null)
                            {
                                Point3D end = alfaCarbon.Position;
                                Cylinder cylinder = new Cylinder(begin, end, radius);
                                container.Children.Add(cylinder);
                            }
                        }
                    }
                }

                #endregion
            }

            // Get bounding box
            Rect3D boundingBox = VisualTreeHelper.GetDescendantBounds(container);
            if (boundingBox.IsEmpty)
            {
                shadowRefreshStarted = false;
                return;
            }

            #region Render Shadow

            const double blurSize = 25;
            const int renderTargetWidth = 200;
            int renderTargetHeight = (int)(200.0 * (boundingBox.SizeX / boundingBox.SizeY));
            RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(renderTargetWidth, renderTargetHeight, 96, 96, PixelFormats.Pbgra32);

            Viewport3D shadowViewport3D = new Viewport3D();
            Border border = new Border();
            border.Padding = new Thickness(blurSize);
            border.Child = shadowViewport3D;

            // Change size of the visualizer
            border.Width = renderTargetBitmap.PixelWidth;
            border.Height = renderTargetBitmap.PixelHeight;
            border.Measure(new Size(renderTargetBitmap.PixelWidth, renderTargetBitmap.PixelHeight));
            border.Arrange(new Rect(0, 0, renderTargetBitmap.PixelWidth, renderTargetBitmap.PixelHeight));

            shadowViewport3D.Children.Add(container);

            // Create camera
            OrthographicCamera orthographicCamera = new OrthographicCamera();

            #region Accomodate camera to fit content

            orthographicCamera.Position = new Point3D(boundingBox.Location.X + boundingBox.SizeX / 2.0,
                                                      boundingBox.Location.Y,
                                                      boundingBox.Location.Z + boundingBox.SizeZ / 2.0);
            orthographicCamera.LookDirection = new Vector3D(0, 1, 0);
            orthographicCamera.UpDirection = new Vector3D(-1, 0, 0);
            orthographicCamera.Width = boundingBox.SizeZ;

            #endregion

            orthographicCamera.NearPlaneDistance = 0;

            // Set the camera & correct lights
            shadowViewport3D.Camera = orthographicCamera;

            BlurEffect blurEffect = new BlurEffect();
            blurEffect.Radius = blurSize;

            border.Effect = blurEffect;

            renderTargetBitmap.Render(border);
            renderTargetBitmap.Freeze();

            #endregion

            // Invoke in main thread
            Dispatcher.BeginInvoke((Action) delegate
            {
                #region Create Plane

                Vector3D margin = new Vector3D(boundingBox.SizeX * 0.4, 0, boundingBox.SizeZ * 0.4);
                Point3D[] points = new Point3D[]
                {
                    boundingBox.Location + new Vector3D(-margin.X, -margin.Y, -margin.Z),
                    boundingBox.Location +
                    new Vector3D(margin.X + boundingBox.SizeX, -margin.Y, -margin.Z),
                    boundingBox.Location +
                    new Vector3D(margin.X + boundingBox.SizeX, -margin.Y,
                                margin.Z + boundingBox.SizeZ),
                    boundingBox.Location +
                    new Vector3D(-margin.X, -margin.Y, margin.Z + boundingBox.SizeZ)
                };

                Polygon shadowPlane = new Polygon();
                shadowPlane.Positions = points;
                shadowPlane.TextureCoordinates = new Point[] { new Point(0, 0), new Point(0, 1), new Point(1, 1), new Point(1, 0) };

                #endregion
                shadowBrush.ImageSource = renderTargetBitmap;
                shadowBrush.Stretch = Stretch.Fill;
                shadowTargetOpacity = 0.8;

                shadowPlane.Material = new DiffuseMaterial(shadowBrush);
                shadowContainer.Children.Clear();
                shadowContainer.Children.Add(shadowPlane);

                // Update shadow hash
                shadowRefreshStarted = false;

              }, DispatcherPriority.SystemIdle);
        }
Beispiel #3
0
        // Create the cap of sheet primitive
        Polygon CreateCap(bool isLower)
        {
            Point3D[] centers = Centers;
            Vector3D[] horizontalVectors = HorizontalVectors;
            Vector3D[] verticalVectors = VerticalVectors;
            double halfWidth = 0.5 * Width;
            double halfHeight = 0.5 * Height;

            // Check the data of premitives
            if(!Sheet.IsValid(centers, horizontalVectors, verticalVectors, halfWidth, halfHeight))
                return null;

            // Create the cap
            int index = isLower ? 0 : centers.Length - 1;
            Point3D center = centers[index];
            Vector3D horizontalVector = halfWidth * horizontalVectors[index];
            Vector3D verticalVector = halfHeight * verticalVectors[index];

            Point3D[] positions = new Point3D[4];
            positions[0] = center - horizontalVector + verticalVector;
            positions[1] = center - horizontalVector - verticalVector;
            positions[2] = center + horizontalVector - verticalVector;
            positions[3] = center + horizontalVector + verticalVector;

            // Reverse points for lower cap
            if (!isLower) Array.Reverse(positions);

            Polygon result = new Polygon();
            result.Positions = positions;
            // Set the same material
            result.Material = Material;
            return result;
        }