Adding a very large vector image - wpf

I need some advice on how to add vector image data to my WPF application. As of now, I simply add the image information as StreamGeometry to the UserControl resources. For example:
<UserControl.Resources>
<ResourceDictionary>
<StreamGeometry x:Key="ProtoLeaf" >m 451.45 512 c 17.06 0 30.43 -13.86 30.43 -31.56 V 31.55 C 481.87 13.86 468.51 0 451.44 0 A 32.94 32.94 0 0 0 434.99 4.52 L 46.29 229 c -10.13 5.85 -16.18 16 -16.18 27 0 11 6 21.2 16.18 27 l 388.7 224.48 a 32.92 32.92 0 0 0 16.45 4.52 z</StreamGeometry>
<StreamGeometry x:Key="ProtoFrog">m 51.45 512 c 17.06 0 30.43 -13.86 30.43 -31.56 V 31.55 C 481.87 13.86 468.51 0 451.44 0 A 32.94 32.94 0 0 0 434.99 4.52 L 46.29 229 c -10.13 5.85 -16.18 16 -16.18 27 0 11 6 21.2 16.18 27 l 388.7 224.48 a 32.92 32.92 0 0 0 16.45 4.52 z</StreamGeometry>
</ResourceDictionary>
</UserControl.Resources>
And then I use these for my path objects.
<Viewbox Margin="97,10,10,10">
<Canvas x:Name="Pond" Background="#FF58CFF1" Margin="4" Height="360" Width="640">
<Path x:Name="Leaf1" Tag="1" Height="80" Width="80" Canvas.Left="50" Canvas.Top="50" RenderTransformOrigin="0.5,0.5" Stretch="Uniform" Fill="#FF30F012" Data="{DynamicResource ProtoLeaf}">
</Path>
I created a couple of fairly large vector images and I have the StreamGeometry data available, but it is HUGE. Thousands of lines, and it breaks the syntax highlighting in visual studio. I don't really know how am I supposed to handle this?

So after thinking about grek40's comment and doing some research in this direction I came up with the following solution. I simply added a MergedDictionaries statement and reference an external file where I have all my SteamGeometry information.
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resources/imagefiles/VectorCollection.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>

Related

WPF Panel in container without PositiveInfinity

I'm trying to create a custom TabControl, where when the items combined width exceeds the width of the panel the items are in, they will resize unified, like the Chrome tabs. I also want to panel to be scrollable when the items can't be contained with their MinWidth. All that works fine already.
My problem is, i want, like the Chrome tabcontrol, to have a "New Tab" button besides the tab panel. To accomplish this, i need to wrap the tab panel and the button in the scrollviewer somehow. But when using a StackPanel or Grid, my tab panel now has it's width with PositiveInfinity, and the MeassureOverride now can't compute the width, of cause.
Here is my code:
<ScrollViewer CanContentScroll="True"
VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="Hidden">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<local:TabPanel Grid.Column="0"
IsItemsHost="True"
SnapsToDevicePixels="True"
Margin="6,5,6,0"/>
<Button Grid.Column="1"
Margin="0,5,0,0"
KeyboardNavigation.TabIndex="2"
Style="{StaticResource NewTabButtonStyle}"
Visibility="{Binding Path=AllowAddNew, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}"
ToolTip="Add a New tab">
<Viewbox RenderOptions.EdgeMode="Aliased"
SnapsToDevicePixels="True" >
<Grid>
<Line X1="0" Y1="20" X2="40" Y2="20" Stroke="{Binding Path=TabForeground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ExtendedTabControl}}}" StrokeThickness="7"/>
<Line X1="20" Y1="0" X2="20" Y2="40" Stroke="{Binding Path=TabForeground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ExtendedTabControl}}}" StrokeThickness="7"/>
</Grid>
</Viewbox>
</Button>
</Grid>
</ScrollViewer>
If i remove the grid and the button inside the ScrollViewer, the TabPanel now has a width and it works.
So how can i accomplish to have my button right of the TabPanel without the TabPanel having Width=PositiveInfinity?
Does something like this do the trick for you? Of cause it needs some touching up but it does the trick. Need to refine the bindings but maybe its can point into a direction
<Grid Height="30" Background="LightBlue" Width="400">
<UniformGrid Rows="1" HorizontalAlignment="Left" Margin="0,0,40,0" Name="uni">
<Border CornerRadius="12,12,0,0" BorderBrush="Blue" BorderThickness="2" MaxWidth="200" HorizontalAlignment="Left" Name="tabitem">
<StackPanel Orientation="Horizontal">
<Viewbox>
<Path Fill="Black" Data="M 22.205078 2 A 1.0001 1.0001 0 0 0 21.21875 2.8378906 L 20.246094 8.7929688 C 19.076509 9.1331971 17.961243 9.5922728 16.910156 10.164062 L 11.996094 6.6542969 A 1.0001 1.0001 0 0 0 10.708984 6.7597656 L 6.8183594 10.646484 A 1.0001 1.0001 0 0 0 6.7070312 11.927734 L 10.164062 16.873047 C 9.583454 17.930271 9.1142098 19.051824 8.765625 20.232422 L 2.8359375 21.21875 A 1.0001 1.0001 0 0 0 2.0019531 22.205078 L 2.0019531 27.705078 A 1.0001 1.0001 0 0 0 2.8261719 28.691406 L 8.7597656 29.742188 C 9.1064607 30.920739 9.5727226 32.043065 10.154297 33.101562 L 6.6542969 37.998047 A 1.0001 1.0001 0 0 0 6.7597656 39.285156 L 10.648438 43.175781 A 1.0001 1.0001 0 0 0 11.927734 43.289062 L 16.882812 39.820312 C 17.936999 40.39548 19.054994 40.857928 20.228516 41.201172 L 21.21875 47.164062 A 1.0001 1.0001 0 0 0 22.205078 48 L 27.705078 48 A 1.0001 1.0001 0 0 0 28.691406 47.173828 L 29.751953 41.1875 C 30.920633 40.838997 32.033372 40.369697 33.082031 39.791016 L 38.070312 43.291016 A 1.0001 1.0001 0 0 0 39.351562 43.179688 L 43.240234 39.287109 A 1.0001 1.0001 0 0 0 43.34375 37.996094 L 39.787109 33.058594 C 40.355783 32.014958 40.813915 30.908875 41.154297 29.748047 L 47.171875 28.693359 A 1.0001 1.0001 0 0 0 47.998047 27.707031 L 47.998047 22.207031 A 1.0001 1.0001 0 0 0 47.160156 21.220703 L 41.152344 20.238281 C 40.80968 19.078827 40.350281 17.974723 39.78125 16.931641 L 43.289062 11.933594 A 1.0001 1.0001 0 0 0 43.177734 10.652344 L 39.287109 6.7636719 A 1.0001 1.0001 0 0 0 37.996094 6.6601562 L 33.072266 10.201172 C 32.023186 9.6248101 30.909713 9.1579916 29.738281 8.8125 L 28.691406 2.828125 A 1.0001 1.0001 0 0 0 27.705078 2 L 22.205078 2 z M 23.056641 4 L 26.865234 4 L 27.861328 9.6855469 A 1.0001 1.0001 0 0 0 28.603516 10.484375 C 30.066026 10.848832 31.439607 11.426549 32.693359 12.185547 A 1.0001 1.0001 0 0 0 33.794922 12.142578 L 38.474609 8.7792969 L 41.167969 11.472656 L 37.835938 16.220703 A 1.0001 1.0001 0 0 0 37.796875 17.310547 C 38.548366 18.561471 39.118333 19.926379 39.482422 21.380859 A 1.0001 1.0001 0 0 0 40.291016 22.125 L 45.998047 23.058594 L 45.998047 26.867188 L 40.279297 27.871094 A 1.0001 1.0001 0 0 0 39.482422 28.617188 C 39.122545 30.069817 38.552234 31.434687 37.800781 32.685547 A 1.0001 1.0001 0 0 0 37.845703 33.785156 L 41.224609 38.474609 L 38.53125 41.169922 L 33.791016 37.84375 A 1.0001 1.0001 0 0 0 32.697266 37.808594 C 31.44975 38.567585 30.074755 39.148028 28.617188 39.517578 A 1.0001 1.0001 0 0 0 27.876953 40.3125 L 26.867188 46 L 23.052734 46 L 22.111328 40.337891 A 1.0001 1.0001 0 0 0 21.365234 39.53125 C 19.90185 39.170557 18.522094 38.59371 17.259766 37.835938 A 1.0001 1.0001 0 0 0 16.171875 37.875 L 11.46875 41.169922 L 8.7734375 38.470703 L 12.097656 33.824219 A 1.0001 1.0001 0 0 0 12.138672 32.724609 C 11.372652 31.458855 10.793319 30.079213 10.427734 28.609375 A 1.0001 1.0001 0 0 0 9.6328125 27.867188 L 4.0019531 26.867188 L 4.0019531 23.052734 L 9.6289062 22.117188 A 1.0001 1.0001 0 0 0 10.435547 21.373047 C 10.804273 19.898143 11.383325 18.518729 12.146484 17.255859 A 1.0001 1.0001 0 0 0 12.111328 16.164062 L 8.8261719 11.46875 L 11.523438 8.7734375 L 16.185547 12.105469 A 1.0001 1.0001 0 0 0 17.28125 12.148438 C 18.536908 11.394293 19.919867 10.822081 21.384766 10.462891 A 1.0001 1.0001 0 0 0 22.132812 9.6523438 L 23.056641 4 z M 25 17 C 20.593567 17 17 20.593567 17 25 C 17 29.406433 20.593567 33 25 33 C 29.406433 33 33 29.406433 33 25 C 33 20.593567 29.406433 17 25 17 z M 25 19 C 28.325553 19 31 21.674447 31 25 C 31 28.325553 28.325553 31 25 31 C 21.674447 31 19 28.325553 19 25 C 19 21.674447 21.674447 19 25 19 z" />
</Viewbox>
<TextBlock VerticalAlignment="Center">Name of tab</TextBlock>
</StackPanel>
</Border>
</UniformGrid>
<Border Grid.Column="1" Width="30" BorderBrush="Blue" BorderThickness="2" CornerRadius="15" HorizontalAlignment="Left">
<Border.Margin>
<MultiBinding Converter="{StaticResource mutliply}">
<Binding ElementName="uni" Path="Children.Count" />
<Binding ElementName="tabitem" Path="ActualWidth" />
</MultiBinding>
</Border.Margin>
<Button BorderBrush="Transparent" Background="Transparent" Padding="0">
+
</Button>
</Border>
</Grid>
requires a converter:
public class Multiplier : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
Thickness thic = new Thickness(1,0,0,0);
foreach (var value in values)
{
thic.Left = thic.Left * System.Convert.ToDouble(value);
}
thic.Left = thic.Left + 5;
return thic;
}//END Convert
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}//END ConvertBack
}//END class MultiVisibilityConverter : IMultiValueConverter

Center path content inside button

I have a very simple path (just a + sign) that I exported from Inkscape and I would like to use it as the content of a button but when I do, the path is off center.
<Button Height="24" Width="24">
<Viewbox HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Fill">
<Path Fill="#000000" Data="M 11 5 L 11 11 L 5 11 L 5 13 L 11 13 L 11 19 L 13 19 L 13 13 L 19 13 L 19 11 L 13 11 L 13 5 L 11 5 z"/>
</Viewbox>
</Button>
I've wrapped it in a Viewbox so I can scale it and I've tried playing with the HorizontalAlignment, VerticalAlignment and LayoutRounding but they don't seem to affect the positioning.
I'm guessing the path data itself is responsible for this..probably starting with the first Move To (M) but I'm not confident with editing the path manually.
Is there any way to correct this so it displays centered inside the button? I have many more buttons to build so I'd like to understand what's going on.
Here's the original SVG:
<svg xmlns="http://www.w3.org/2000/svg" version="1" viewBox="0 0 24 24" enable-background="new 0 0 24 24" width="48" height="48">
<path style="text-indent:0;text-align:start;line-height:normal;text-transform:none;block-progression:tb;-inkscape-font-specification:Bitstream Vera Sans" d="M 11 5 L 11 11 L 5 11 L 5 13 L 11 13 L 11 19 L 13 19 L 13 13 L 19 13 L 19 11 L 13 11 L 13 5 L 11 5 z" color="#000" overflow="visible" enable-background="accumulate" font-family="Bitstream Vera Sans"/>
Thank You!!
Use something like this:
<Button Width="24" Height="24">
<Path Margin="2"
Data="M 11 5 L 11 11 L 5 11 L 5 13 L 11 13 L 11 19 L 13 19 L 13 13 L 19 13 L 19 11 L 13 11 L 13 5 L 11 5 z"
Fill="#000000"
Stretch="Fill" />
</Button>
No need for a ViewBoxwhen you have a Path

IndexedFaceSet creates extra faces in x3d file

I have created an x3d file using x3dom. Following is the structure of the file. Copy the following code into text editor and save it as .x3d file. For imgage texture you can consider any jpg file and place it at the same location as x3d.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.0//EN"
"http://www.web3d.org/specifications/x3d-3.0.dtd">
<X3D profile='Interchange' version='3.0'
xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance'
xsd:noNamespaceSchemaLocation='http://www.web3d.org/specifications/x3d-3.0.xsd'>
<Scene>
<NavigationInfo type='"EXAMINE" "WALK" "FLY" "ANY"'/>
<DirectionalLight intensity="0.8" direction="0 1 0"/>
<DirectionalLight intensity="0.9" direction="0 -1 0"/>
<DirectionalLight intensity="0.6" direction="1 0 -1"/>
<DirectionalLight intensity="0.6" direction="-1 0 -1"/>
<DirectionalLight intensity="0.6" direction="-1 0 1"/>
<DirectionalLight intensity="0.6" direction="1 0 1"/>
<Shape>
<Appearance>
<Material ambientIntensity="0.2" diffuseColor="0.004 0.004 0.004" emissiveColor="0 0 0" shininess="0.2" specularColor="0 0 0" transparency="0"/>
<ImageTexture url="Penguins.jpg"/>
</Appearance>
<IndexedFaceSet convex="true" coordIndex="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 -1 " ccw="true">
<Coordinate point="132.2349 0 329.9732 123.0347 0 336.9273 109.9391 0 350.0229 102.985 0 359.223 82.26761 0 386.6317 69.30841 0 436.438 74.03987 0 470.4683 78.77134 0 504.4987 104.8261 0 548.8805 132.2349 0 569.598 191.8598 0 569.598 191.8598 0 689.9727 911.8589 0 689.9727 1032.234 0 569.598 1032.234 0 270.3483 852.2339 0 270.3483 852.2339 0 210.7232 371.8596 0 210.7232 371.8596 0 329.9732"/>
</IndexedFaceSet>
</Shape>
<Viewpoint description="Center of Space" fieldOfView="0.785" position="553.1368 60 450.348"/>
</Scene>
</X3D>
Looking it from the top view the 3D object looks like this,
enter image description here
And from the bottom view it looks like this,
enter image description here
I have checked all the points and they are in proper sequence but not sure why these two extra faces are created. Anything I am doing wrong here?
You draw a non-convex shape, therefor you need to set convex to false, in addition if you want to see your shape from "behind" you need to set solid to false.
This works:
<IndexedFaceSet convex="false" solid="false" coordIndex="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 -1">
(you dont need ccw, its true by default)

Draw Cylinder Path in Expression Blend 4

I am trying to "draw" a simple cylinder path in Expression Blend 4, and I can't seem to get it quite right.
(1) I started out by adding two Ellipses and one Rectangle:
<Grid Background="Transparent">
<Ellipse Fill="Transparent" Height="13.25" Margin="352,0,352,227" Stroke="Black" VerticalAlignment="Bottom"/>
<Rectangle Fill="Transparent" Margin="352,216,352,233" Stroke="Black"/>
<Ellipse Fill="Transparent" Height="13.25" Margin="352,209.625,352,0" Stroke="Black" VerticalAlignment="Top"/>
</Grid>
(2) Next, I selected the bottom Ellipse and Rectangle, and performed a Combine -> Unite:
<Grid Background="Transparent">
<Path Data="M0.5,0.5 L47.5,0.5 47.5,47.375 47.5,47.5 47.493931,47.5 47.492325,47.533089 C47.170608,50.84277 36.775898,53.5 24,53.5 11.2241,53.5 0.82939076,50.84277 0.50767487,47.533089 L0.50606853,47.5 0.5,47.5 0.5,47.375 z" Fill="Transparent" Margin="352,216,352,227" Stretch="Fill" Stroke="Black"/>
<Ellipse Fill="Transparent" Height="13.25" Margin="352,209.625,352,0" Stroke="Black" VerticalAlignment="Top"/>
</Grid>
(3) Next, I selected the top Ellipse and the Path resulting from step 2 and then performed a Path -> Make Compound Path. Then with the direct selection tool, I removed the line cutting though the top Ellipse. It looks good until I try and apply a Fill="Green" to the Path.
<Grid Background="Transparent">
<Path Fill="Green" Data="M47.5,6.875 L47.5,53.75 47.5,53.875 47.493931,53.875 47.492325,53.908089 C47.170608,57.21777 36.775898,59.875 24,59.875 11.2241,59.875 0.82939076,57.21777 0.50767487,53.908089 L0.50606853,53.875 0.5,53.875 0.5,53.75 0.5,6.875 M47.5,6.625 C47.5,10.007744 36.978692,12.75 24,12.75 11.021308,12.75 0.5,10.007744 0.5,6.625 0.5,3.2422559 11.021308,0.5 24,0.5 36.978692,0.5 47.5,3.2422559 47.5,6.625 z" Margin="352,209.625,352,227" Stretch="Fill" Stroke="Black"/>
</Grid>
I've tried various operations, but I can't for the life of me figure out how to get a cylindrical Path where I can apply a Fill to the entire thing.
Don't know how to do that in Blend, but that figure could be made up of two arcs for (two halves of) the upper ellipse, one line down, one arc for the lower half ellipse, one line up and a final arc for half of the upper ellipse:
<Path Stroke="Black" Fill="LightGreen" Stretch="Fill" Data="
M0,0
A50,10 0 0 0 100,0
A50,10 0 0 0 0,0
M100,00 L100,100
A50,10 0 0 1 0,100
L0,0
A50,10 0 0 0 100,0" />
Is there a way to make it tilted tho? I am trying to shift this to give it an near-isometric look, but can't quite figure it out. Would the way to go be to have the circle shifted? So that the sides are at 10 and 4 or similar (as on a clock)?
Been working on this, but I either get an overlap in the bottom left, or some pixels outside of the circle.
<Path Stroke="Black" Fill="AliceBlue" Data="
M 0 0
A 45,40 0 0 0 100,0
A 45,40 0 0 0 0,0
L 15,-100
A 45,40 0 0 1 115,-100
L 100,0
A 45,40 0 0 0 0,0
"/>
EDIT: I more or less managed now, some minor tweaks and it should be there, the trick was to rotate the circles before adding the lines.
<Path Stroke="Black" Fill="AliceBlue" Data="
M 0 0
A 45,40 0 0 0 100,45
A 45,40 0 0 0 0,0
L 60,-100
A 45,40 0 0 1 160,-60
L 100,45
A 45,40 0 0 0 0,0
"/>

How can I use SnapToDevicePixels and StrokeDashArray

I have the following XAML code:
<Path Data="M0,0 L 12 0 L 12 12 L 0 12 Z M 6 0 L 6 12 M 0 6 L 12 6" StrokeDashArray="1 1" Stroke="Black" StrokeThickness="1" SnapsToDevicePixels='True">
</Path>
However it looks horribly fuzzy on my screen.
Is there a solution?
If you just want a crisp, dashed path and you may be able to get the results you want by declaring the RenderOptions.EdgeMode as Aliased to prevent the framework from interpolating the path outline when a dash falls between pixel boundaries:
<Path Data="M0,0 L 12 0 L 12 12 L 0 12 Z M 6 0 L 6 12 M 0 6 L 12 6" StrokeDashArray="1 1" Stroke="Black" StrokeThickness="1" RenderOptions.EdgeMode="Aliased">
</Path>

Resources