/// <summary> /// Plots colour scaled stress in each element /// </summary> public void PlotUnSmoothedStress() { // clear existing plots ClearPlots(); // get canvas dimensions/properties double originX = OriginOffsetX , originY = OriginOffsetY , scale = Scale , yHeight = ActualHeight; Units units = Units; // get units dependent scaling factor double factor; switch ( units ) { case Units.Metres: factor = 0.0254; break; case Units.Millimetres: factor = 25.4; break; case Units.Feet: factor = 1.0 / 12.0; break; default: factor = 1.0; break; } // set plot type MenuItem unSmoothedMenu = (MenuItem) ((MenuItem) ((Menu) ((DockPanel) ((Grid) ((Grid) this.Parent).Parent).Children[0]).Children[0]).Items[1]).Items[4]; int plotType = 0; for ( int i = 0 ; i < unSmoothedMenu.Items.Count ; i++ ) { if ( ((MenuItem) unSmoothedMenu.Items[i]).IsChecked ) { plotType = i; break; } } // load appropriate stress values List<double> stress; double minVal , maxVal; switch ( plotType ) { case 0: // XX stress = sxxE; maxVal = minSxxE; minVal = maxSxxE; break; case 1: // YY stress = syyE; maxVal = minSyyE; minVal = maxSyyE; break; case 2: // XY stress = sxyE; maxVal = minSxyE; minVal = maxSxyE; break; case 3: // ZZ stress = szzE; maxVal = minSzzE; minVal = maxSzzE; break; default: // FBAR stress = fbarE; minVal = minFbarE; maxVal = maxFbarE; break; } // compute key values for colour scale double diff = maxVal - minVal; double qdiff = 0.25 * diff; double lowQVal = minVal + 0.25 * diff; double midVal = minVal + 0.5 * diff; double uppQVal = minVal + 0.75 * diff; // set mesh to regular coords and // create fill colours based on stress // at integration points Polygon newPolygon; double x , y; fe3NodedTriElement newElement; byte r , g , b; double st; for ( int i = 0 ; i < triElements.Count ; i++ ) { if ( triElements[i].Material == null ) continue; // skip inactive elements newElement = new fe3NodedTriElement( triElements[i].Number , nodes[triElements[i].Nodes[0].Number] , nodes[triElements[i].Nodes[1].Number] , nodes[triElements[i].Nodes[2].Number] , false , false , null , false ); newPolygon = new Polygon(); newPolygon.StrokeThickness = 0; newPolygon.Stroke = Brushes.Transparent; newPolygon.Opacity = 1.0; // compute fill colour st = stress[i]; if ( plotType == 4 ) { if ( st <= minVal ) { r = 0; g = 0; b = 255; } else if ( st < lowQVal ) { r = 0; g = (byte) (255 * (st - minVal) / qdiff); b = 255; } else if ( st < midVal ) { r = 0; g = 255; b = (byte) (255 * (1 - (st - lowQVal) / qdiff)); } else if ( st < uppQVal ) { r = (byte) (255 * (st - midVal) / qdiff); g = 255; b = 0; } else if ( st < maxVal ) { r = 255; g = (byte) (255 * (1 - (st - uppQVal) / qdiff)); b = 0; } else { r = 255; g = 0; b = 0; } } else { if ( st >= minVal ) { r = 0; g = 0; b = 255; } else if ( st > lowQVal ) { r = 0; g = (byte) (255 * (st - minVal) / qdiff); b = 255; } else if ( st > midVal ) { r = 0; g = 255; b = (byte) (255 * (1 - (st - lowQVal) / qdiff)); } else if ( st > uppQVal ) { r = (byte) (255 * (st - midVal) / qdiff); g = 255; b = 0; } else if ( st > maxVal ) { r = 255; g = (byte) (255 * (1 - (st - uppQVal) / qdiff)); b = 0; } else { r = 255; g = 0; b = 0; } } newPolygon.Fill = new SolidColorBrush( Color.FromRgb( r , g , b ) ); foreach ( feNode node in newElement.Nodes ) { x = node.X / (scale * factor) * dpiX + originX; y = yHeight - (node.Y / (scale * factor) * dpiY + originY); newPolygon.Points.Add( new Point( x , y ) ); } newElement.Boundary = newPolygon; stressTriMesh.Add( newElement ); } // refresh plotting axes BuildAxes(); }
/// <summary> /// Plots deformed mesh output /// </summary> public void PlotDeformedMesh( bool autoMag = true ) { // clear existing plots ClearPlots(); // get canvas dimensions/properties double originX = OriginOffsetX , originY = OriginOffsetY , scale = Scale , yHeight = ActualHeight; Units units = Units; // get units dependent scaling factor double factor; switch ( units ) { case Units.Metres: factor = 0.0254; break; case Units.Millimetres: factor = 25.4; break; case Units.Feet: factor = 1.0 / 12.0; break; default: factor = 1.0; break; } Polygon newPolygon; double x , y; // compute magnification if ( autoMag ) Magnification = 0.25 * 0.5 * (feaParams.RowHeight + feaParams.ColWidth) / maxDisp; // compute deformed coordinates deformedNodes.Clear(); deformedNodes.Add( null ); int numPhases = source.AnalysisPhases.Count - 1; for ( int i = 1 ; i < nodes.Count ; i++ ) { deformedNodes.Add( new feNode( i , false , nodes[i].X + Magnification * disp[i][0] , nodes[i].Y + Magnification * disp[i][1] , numPhases ) ); } // set mesh to deformed coords fe3NodedTriElement newElement; foreach ( fe3NodedTriElement element in triElements ) { if ( element.Material == null ) continue; // skip inactive elements newElement = new fe3NodedTriElement( element.Number , deformedNodes[element.Nodes[0].Number] , deformedNodes[element.Nodes[1].Number] , deformedNodes[element.Nodes[2].Number] , false , false , element.Material , false ); newPolygon = new Polygon(); newPolygon.StrokeThickness = 0.8; newPolygon.Stroke = Brushes.Red; newPolygon.Opacity = /*1.0*/ 0.8; newPolygon.Fill = /*Brushes.White*/ element.Material.Fill; foreach ( feNode node in newElement.Nodes ) { x = node.X / (scale * factor) * dpiX + originX; y = yHeight - (node.Y / (scale * factor) * dpiY + originY); newPolygon.Points.Add( new Point( x , y ) ); } newElement.Boundary = newPolygon; deformedTriMesh.Add( newElement ); } // refresh plotting axes BuildAxes(); }
/// <summary> /// Plots colour scaled contours based on polynomial /// smoothed stresses at each node. /// </summary> public void PlotSmoothedStress() { // clear existing plots ClearPlots(); // get canvas dimensions/properties double originX = OriginOffsetX , originY = OriginOffsetY , scale = Scale , yHeight = ActualHeight; Units units = Units; // get units dependent scaling factor double factor; switch ( units ) { case Units.Metres: factor = 0.0254; break; case Units.Millimetres: factor = 25.4; break; case Units.Feet: factor = 1.0 / 12.0; break; default: factor = 1.0; break; } // set plot type MenuItem smoothedMenu = (MenuItem) ((MenuItem) ((Menu) ((DockPanel) ((Grid) ((Grid) this.Parent).Parent).Children[0]).Children[0]).Items[1]).Items[3]; int plotType = 0; for ( int i = 0 ; i < smoothedMenu.Items.Count ; i++ ) { if ( ((MenuItem) smoothedMenu.Items[i]).IsChecked ) { plotType = i; break; } } // load appropriate stress values List<double> stress; double minVal , maxVal; switch ( plotType ) { case 0: // XX stress = sxxN; maxVal = minSxxN; minVal = maxSxxN; break; case 1: // YY stress = syyN; maxVal = minSyyN; minVal = maxSyyN; break; case 2: // XY stress = sxyN; maxVal = minSxyN; minVal = maxSxyN; break; case 3: // ZZ stress = szzN; maxVal = minSzzN; minVal = maxSzzN; break; default: // FBAR stress = fbarN; minVal = minFbarN; maxVal = maxFbarN; break; } // compute key values for colour scale double diff = maxVal - minVal; double qdiff = 0.25 * diff; double lowQVal = minVal + 0.25 * diff; double midVal = minVal + 0.5 * diff; double uppQVal = minVal + 0.75 * diff; // set mesh to regular coords and // create fill colours based on stress // at integration points Polygon newPolygon; double x , y; fe3NodedTriElement newElement; byte r , g , b; double st; double x1 , y1 , x2 , y2 , x3 , y3 , s1 , s2 , s3 , x_min , x_max , x_ymin , y_min , y_xmax, s_ymin , s_xymin , s_xmax , dsdx , dsdy , dydx , detA , detA1 , detA2; for ( int i = 0 ; i < triElements.Count ; i++ ) { if ( triElements[i].Material == null ) continue; // skip inactive elements newElement = new fe3NodedTriElement( triElements[i].Number , nodes[triElements[i].Nodes[0].Number] , nodes[triElements[i].Nodes[1].Number] , nodes[triElements[i].Nodes[2].Number] , false , false , null , false ); newPolygon = new Polygon(); newPolygon.StrokeThickness = 0; newPolygon.Stroke = Brushes.Transparent; newPolygon.Opacity = 1.0; // compute linear gradient brush values x_min = double.MaxValue; x_max = double.MinValue; y_min = double.MaxValue; x_ymin = 0; s_ymin = 0; foreach ( feNode node in newElement.Nodes ) { if ( node.X < x_min ) x_min = node.X; if ( node.X > x_max ) x_max = node.X; if ( node.Y < y_min ) { y_min = node.Y; x_ymin = node.X; s_ymin = stress[node.Number]; } x = node.X / (scale * factor) * dpiX + originX; y = yHeight - (node.Y / (scale * factor) * dpiY + originY); newPolygon.Points.Add( new Point( x , y ) ); } x1 = newElement.Nodes[0].X; y1 = newElement.Nodes[0].Y; s1 = stress[newElement.Nodes[0].Number]; x2 = newElement.Nodes[1].X; y2 = newElement.Nodes[1].Y; s2 = stress[newElement.Nodes[1].Number]; x3 = newElement.Nodes[2].X; y3 = newElement.Nodes[2].Y; s3 = stress[newElement.Nodes[2].Number]; detA = (x2 * y3 - x3 * y2) - (x1 * y3 - x3 * y1) + (x1 * y2 - x2 * y1); detA1 = (s2 * y3 - s3 * y2) - (s1 * y3 - s3 * y1) + (s1 * y2 - s2 * y1); detA2 = (x2 * s3 - x3 * s2) - (x1 * s3 - x3 * s1) + (x1 * s2 - x2 * s1); dsdx = detA1 / detA; dsdy = detA2 / detA; dydx = dsdx / dsdy; s_xymin = s_ymin - dsdx * (x_ymin - x_min); y_xmax = y_min + dydx * (x_max - x_min); s_xmax = s_xymin + dsdx * (x_max - x_min) + dsdy * (y_xmax - y_min); // compute fill colour st = s_xymin; if ( plotType == 4 ) { if ( st <= minVal ) { r = 0; g = 0; b = 255; } else if ( st < lowQVal ) { r = 0; g = (byte) (255 * (st - minVal) / qdiff); b = 255; } else if ( st < midVal ) { r = 0; g = 255; b = (byte) (255 * (1 - (st - lowQVal) / qdiff)); } else if ( st < uppQVal ) { r = (byte) (255 * (st - midVal) / qdiff); g = 255; b = 0; } else if ( st < maxVal ) { r = 255; g = (byte) (255 * (1 - (st - uppQVal) / qdiff)); b = 0; } else { r = 255; g = 0; b = 0; } } else { if ( st >= minVal ) { r = 0; g = 0; b = 255; } else if ( st > lowQVal ) { r = 0; g = (byte) (255 * (st - minVal) / qdiff); b = 255; } else if ( st > midVal ) { r = 0; g = 255; b = (byte) (255 * (1 - (st - lowQVal) / qdiff)); } else if ( st > uppQVal ) { r = (byte) (255 * (st - midVal) / qdiff); g = 255; b = 0; } else if ( st > maxVal ) { r = 255; g = (byte) (255 * (1 - (st - uppQVal) / qdiff)); b = 0; } else { r = 255; g = 0; b = 0; } } Color startColour = Color.FromRgb( r , g , b ); Point startPoint = new Point( x_min / (scale * factor) * dpiX + originX , y = yHeight - (y_min / (scale * factor) * dpiY + originY) ); st = s_xmax; if ( plotType == 4 ) { if ( st <= minVal ) { r = 0; g = 0; b = 255; } else if ( st < lowQVal ) { r = 0; g = (byte) (255 * (st - minVal) / qdiff); b = 255; } else if ( st < midVal ) { r = 0; g = 255; b = (byte) (255 * (1 - (st - lowQVal) / qdiff)); } else if ( st < uppQVal ) { r = (byte) (255 * (st - midVal) / qdiff); g = 255; b = 0; } else if ( st < maxVal ) { r = 255; g = (byte) (255 * (1 - (st - uppQVal) / qdiff)); b = 0; } else { r = 255; g = 0; b = 0; } } else { if ( st >= minVal ) { r = 0; g = 0; b = 255; } else if ( st > lowQVal ) { r = 0; g = (byte) (255 * (st - minVal) / qdiff); b = 255; } else if ( st > midVal ) { r = 0; g = 255; b = (byte) (255 * (1 - (st - lowQVal) / qdiff)); } else if ( st > uppQVal ) { r = (byte) (255 * (st - midVal) / qdiff); g = 255; b = 0; } else if ( st > maxVal ) { r = 255; g = (byte) (255 * (1 - (st - uppQVal) / qdiff)); b = 0; } else { r = 255; g = 0; b = 0; } } Color endColour = Color.FromRgb( r , g , b ); Point endPoint = new Point( x_max / (scale * factor) * dpiX + originX , y = yHeight - (y_xmax / (scale * factor) * dpiY + originY) ); newPolygon.Fill = new LinearGradientBrush( startColour , endColour , startPoint , endPoint ); newElement.Boundary = newPolygon; stressTriMesh.Add( newElement ); } // refresh plotting axes BuildAxes(); }