Thursday, March 31, 2011

C#: I want to pass messages like a file path to my forms application like a console application, how would I do that?

C#: I want to pass messages like a file path to my forms application like a console application, how would I do that?

I was told I needed to find my main method to add string[] args, but I wouldn't know which one that would be in Windows Forms. Which would my main method be in C# windows forms application?

From stackoverflow
  • If you want to get access to the command line parameters, use Environment.CommandLine

    string args = Environment.CommandLine;
    

    You can do this whether or not you have a main method with string[] args in your code.

  • There's one Main(), which is inside Program.cs. But in WinForms app Environment.GetCommandLineArgs() will be a better option.

  • in your public constructor, use the following:

    string[] args = Environment.GetCommandLineArgs();

    this will give you a string array of the arguments.

  • Ok, string[] args = Environment.GetCommandLineArgs() is a better option. But I will keep the following answer as an alternative to it.

    Look for a file called Program.cs containing the following code fragment...

    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
    

    and change that to

    static class Program
    {
    
        public static string[] CommandLineArgs { get; private set;}
    
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            CommandLineArgs = args;
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
    

    Then access the command line args from your form ...

    Program.CommandLineArgs
    
  • Your Main() method is located in Program.cs file, typically like this:

    [STAThread]
    static void Main()
    {
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Application.Run(new Form1());
    }
    

    You should modify the Main() to the following:

    static void Main(string[] args)
    

    You'll have access to the arguments passed.

    Also, you could access the arguments using Environment.GetCommandLineArgs()

  • hey guise when i do so with my application i get the following string "D:\MyData~1\MyMain~1.pfb" and it supposed to be like that "D:\My Data\My Main Phone Book.pbf" and i don't know why pls any bodyhas asolution to this

    Matt Ellen : Hi falcon eyes, you need to ask this as a separate question - i.e. as its own question. be sure to give an example of the code you're running and the output you're getting.

Bugzilla: Set permissions to make a product readonly for all users.

Hi,

i am using a single instance of Bugzilla for issue tracking in multiple projects. Some of my projects are restricted to be visible only to a single group of people while other projects have to be ready-only for everybody (even if they do not have a user account in bugzilla). Submitting bugs should always only be possible for authenticated users. Editing bugs is also restricted only to a small group of people and the bug reporter himself.

Does somebody know how i have to set permissions in bugzilla if i want to make a single project read-only for all users (without logging in)? At the moment you can only view bugs if you have logged in.

Update As sereda described "requirelogin" is turned "off". I also have a group corresponding to each product.

For each product i have set the group access to: ProductXY: Mandatory/Mandatory, ENTRY

User are added to the groups by Regex (".*" for all users) in the group properties.

But when i try to open a bug as anonymous user bugzilla says "You are not authorized to access bug #8. To see this bug, you must first log in to an account with the appropriate permissions."

From stackoverflow
  • You can make all projects readable anonymously by default by setting "requirelogin" to off in Adminitration | Parameters | User Authentication. Then you would need to check if those products that you don't want to be publicly visible have correct group security (I think it should be mandatory/mandatory setting for a group corresponding to each product).

    Update

    I believe that for a bug to be visible to an anonymous user, it must not belong to any group. Since all your products have 'mandatory' settings, all product bugs belong to corresponding product group, and so not ever visible to anonymous.

    I'd suggest to change group controls for public products to "Shown/NA", and then mass update all bugs and remove them from all groups.

    Alexander : Updated my original post. Seems like it has to be another permission.

PHP and outputting one-to-many results

I've only dealt with one-to-one relationships in php so far, but I'm stuck on a problem which involves a one-to-many relationship. I've been sitting on this for a few days with no luck, so I'm desperate for someone to step in and show me a solution before I lose my mind.

In my database have a series of urls, which are received by a SELECT query along with various other fields, from different tables. Every url has at least one category associated with it, but can have multiple categories. So in my results I might see something that looks a bit like this:

link_id = 3   url= 'http://www.somesite1.com'   category = 'uncategorised'
link_id = 4   url= 'http://www.somesite2.com'   category = 'travel'
link_id = 4   url= 'http://www.somesite2.com'   category = 'fun'
link_id = 4   url= 'http://www.somesite2.com'   category = 'misc'
link_id = 3   url= 'http://www.somesite3.com'   category = 'uncategorised'

I have got this to work, kind of. When I loop through and print them off, using a while loop and mysql fetch array, the result looks exactly like it does above. Thats great, except what I need is for it to read something like:

link_id = 4   url = 'http://www.somesite2.com'   category = 'travel fun misc'

So that basically all of the categories for each url get combined somehow, as they are printed out. My first attempt led me to try a nested while loop, but it didn't work and i'm not sure if this is feasible. Apart from that I'm wondering if I might need a multidimensional array (complete guess, i've never had to use one before).

I'm ordering these results by link id as above, so I know if the link id in the current loop iteration, matches the one in the last iteration - then I have something which has more than one category.. I think I'm really close, but I just can't figure it out.

Any ideas?

From stackoverflow
  • You should be using a connection table.

    1st you have a table of links

    id = 1 url = something
    id = 2 url = something else
    

    Then you have a table of categories

    id = 1 category = something
    id = 2 category = something else
    

    Then you have a connection table

    url_id = 1 category_id = 1
    url_id = 1 category_id = 2
    url_id = 2 category_id = 1
    

    This should atleast get you started.

    Jon : ahh sorry, I should have made it a bit more clear. If I understand correctly, I do have a set up like this. A table called categories, just being a repository of all the categories that exist, then a table that just contains urls, then a table with url_id's and cat_id's to join them together.
    Ólafur Waage : No problem :) I'll keep the answer until you update the question if you want to do that.
  • use an array keyed on the id and url iterate through the values and add to it as follows:

    $link_categories[ $id ] .= $category." ";
    
    $result = mysql_query("SElECT * FROM LINKS");
    
    $link_categories = array();
    
    while ($row = mysql_fetch_array($result,MYSQL_ASSOC))
    {
        if (!isset($link_categories[$row['link']]))
            $link_categories[$row['link']] = " ";
        else
            $link_categories[$row['link']] .= " ";
    
        $link_categories[$row['link']] .= $row['category'];
    }
    
    print_r($link_categories);
    

    Results in:

    Array
    (
        [http://a.com] =>  test evaluate performance
        [http://b.com] =>  classify reduce
        [http://c.com] =>  allocate
    )
    

    This isn't the 'right' way of doing this - really the relationships should be defined in a seperate table with a 1-many relationship.

  • you need to use a control break algorithm.

    set last_link variable to null
    set combined_category to null
    exec query
    
    loop over result set {
        if last_link == null {
            last_link=fetch_link
        }
        if fetch_link==last_link {
            set combined_category+=ltrim(' '.fetch_category)
        } else {
            display html for last_link and combined_category
            set last_link=fetch_link
            set combined_category=fetch_category
        }
    }//loop
    
    display html for last_link and combined_category
    

    I used "display html" as a generic "work" event, you could push this out to a array structure, etc. instead...

  • There is also the "GROUP_CONCAT" function in mysql. That should do exactly what you want to achieve.

    Something like :

    SELECT url, GROUP_CONCAT(category) AS categories FROM yourtable GROUP BY url
    
    Jon : This worked perfectly when I ran the query, and again when I plugged it into my php script. I wasn't aware of that function, but it was exactly what I was after. Thanks!

Grouping data with Linq or not possibe?

I have a List of concrete objects. Some require to be analyzed to take a decision to which one will be kept (when the group contain more than 1 occurence).

Here is a simplified example:

 List<MyObject> arrayObject = new List<MyObject>();
 arrayObject.Add(new MyObject { Id = 1, Name = "Test1", Category = "Cat1"});
 arrayObject.Add(new MyObject { Id = 2, Name = "Test2", Category = "Cat2" });
 arrayObject.Add(new MyObject { Id = 2, Name = "Test2", Category = "Cat3" });

This will required to be at the end of the analyze only :

 arrayObject.Add(new MyObject { Id = 1, Name = "Test1", Category = "Cat1"});
 arrayObject.Add(new MyObject { Id = 2, Name = "Test2", Category = "Cat3" });

As you see the Id2 with Cat2 is gone because the business logic took it off. So what should be done is to be able to get those who have more than 1 category and to apply a logic on it.

Here is what I have so far :

        List<MyObject> arrayObject = new List<MyObject>();
        arrayObject.Add(new MyObject { Id = 1, Name = "Test1", Category = "Cat1"});
        arrayObject.Add(new MyObject { Id = 2, Name = "Test2", Category = "Cat2" });
        arrayObject.Add(new MyObject { Id = 2, Name = "Test2", Category = "Cat3" });


        var filtered = from arrayObject1 in arrayObject
                        group arrayObject by new { arrayObject1.Id, arrayObject1.Name }
                        into g
                        select new { KKey = g.Key, Obj = g };


        foreach(var c in filtered)
        {
            Console.WriteLine(c.KKey + ":" + c.Obj.Count());
            foreach (var cc in c.Obj)
            {
                //Put some Business Logic here to get only 1... but to simplify will just print
                Console.WriteLine("--->" + cc);
            }
        }

The problem is 1) cc is not of type MyObject, second, I have to get all properties in the group by new... I might have few objects that will be different.

Is it possible with Linq? Cause, I can do it without using Linq... but I am trying to apply new stuff of this framework (3.5) as much as I can. Thank

From stackoverflow
  • The problem is in the line that says:

    group arrayObject by
    

    It should say:

    group arrayObject1 by
    
    Daok : Oh my! Not it works. Do you have an idea that will let me not have to add all field in the group arrayObject1 by new { arrayObject1.Id, arrayObject1.Name }. In fact the real object has several property. Isn't there a way to group by "all field except x"?

C to Python via SWIG: can't get void** parameters to hold their value

I have a C interface that looks like this (simplified):

extern bool Operation(void ** ppData);
extern float GetFieldValue(void* pData);
extern void Cleanup(p);

which is used as follows:

void * p = NULL;
float theAnswer = 0.0f;
if (Operation(&p))
{
   theAnswer = GetFieldValue(p);
   Cleanup(p);
}

You'll note that Operation() allocates the buffer p, that GetFieldValue queries p, and that Cleanup frees p. I don't have any control over the C interface -- that code is widely used elsewhere.

I'd like to call this code from Python via SWIG, but I was unable to find any good examples of how to pass a pointer to a pointer -- and retrieve its value.

I think the correct way to do this is by use of typemaps, so I defined an interface that would automatically dereference p for me on the C side:

%typemap(in) void** {
   $1 = (void**)&($input);
}

However, I was unable to get the following python code to work:

import test
p = None
theAnswer = 0.0f
if test.Operation(p):
   theAnswer = test.GetFieldValue(p)
   test.Cleanup(p)

After calling test.Operation(), p always kept its initial value of None.

Any help with figuring out the correct way to do this in SWIG would be much appreciated. Otherwise, I'm likely to just write a C++ wrapper around the C code that stops Python from having to deal with the pointer. And then wrap that wrapper with SWIG. Somebody stop me!

Edit:

Thanks to Jorenko, I now have the following SWIG interface:

% module Test 
%typemap (in,numinputs=0) void** (void *temp)
{
    $1 = &temp;
}

%typemap (argout) void**
{
    PyObject *obj = PyCObject_FromVoidPtr(*$1, Cleanup);
    $result = PyTuple_Pack(2, $result, obj);
}
%{
extern bool Operation(void ** ppData); 
extern float GetFieldValue(void *p); 
extern void Cleanup(void *p);
%} 
%inline 
%{ 
    float gfv(void *p){ return GetFieldValue(p);} 
%} 

%typemap (in) void*
{
    if (PyCObject_Check($input))
    {
        $1 = PyCObject_AsVoidPtr($input);
    }
}

The python code that uses this SWIG interface is as follows:

import test 
success, p = test.Operation()
if success:
   f = test.GetFieldValue(p) # This doesn't work 
   f = test.gvp(p) # This works! 
   test.Cleanup(p)

Oddly, in the python code, test.GetFieldValue(p) returns gibberish, but test.gfv(p) returns the correct value. I've inserting debugging code into the typemap for void*, and both have the same value of p! The call Any ideas about that?

From stackoverflow
  • Would you be willing to use ctypes? Here is sample code that should work (although it is untested):

    from ctypes import *
    
    test = cdll("mydll")
    
    test.Operation.restype = c_bool
    test.Operation.argtypes = [POINTER(c_void_p)]
    
    test.GetFieldValue.restype = c_float
    test.GetFieldValue.argtypes = [c_void_p]
    
    test.Cleanup.restype = None
    test.Cleanup.argtypes = [c_void_p]
    
    if __name__ == "__main__":
        p = c_void_p()
        if test.Operation(byref(p)):
            theAnswer = test.GetFieldValue(p)
            test.Cleanup(p)
    
    Jason Sundram : Thanks -- I'd prefer to use SWIG if I can, but if it doesn't work out, I may consider ctypes.
  • I agree with theller, you should use ctypes instead. It's always easier than thinking about typemaps.

    But, if you're dead set on using swig, what you need to do is make a typemap for void** that RETURNS the newly allocated void*:

    %typemap (in,numinputs=0) void** (void *temp)
    {
        $1 = &temp;
    }
    
    %typemap (argout) void**
    {
        PyObject *obj = PyCObject_FromVoidPtr(*$1);
        $result = PyTuple_Pack(2, $result, obj);
    }
    

    Then your python looks like:

    import test
    success, p = test.Operation()
    theAnswer = 0.0f
    if success:
       theAnswer = test.GetFieldValue(p)
       test.Cleanup(p)
    

    Edit:

    I'd expect swig to handle a simple by-value void* arg gracefully on its own, but just in case, here's swig code to wrap the void* for GetFieldValue() and Cleanup():

    %typemap (in) void*
    {
        $1 = PyCObject_AsVoidPtr($input);
    }
    
    Jason Sundram : Thanks for the swig. test.Operation() now works, but I'm having trouble calling test.GetFieldValue(p) from the python code. Do I need a typemap for void* as well?
    Jorenko : Weird. I added a typemap for that to my answer, just in case, though I haven't had a chance to test it...
    Jason Sundram : Thanks -- so this is a bit weird. Without the typemap, GetFieldValue claims that p is null. With the typemap, there are no complaints, but I get back a garbage value in theAnswer.
    Jorenko : Well, keep in mind that the typemaps are actual C snippets that get inserted before/after the wrapped function call. If you like you can put debug prints, etc there to try to work out what the problem is.
    Jason Sundram : Thanks -- Here's the interface (+ your stuff): % module Test %{ extern float GetFieldValue(void *p); }% %inline %{ float gfv(void *p){ return GetFieldValue(p);} %} Oddly, test.GetFieldValue(p) returns gibberish, but test.gfv(p) returns the correct value. But both have the same value of p!
    Jason Sundram : Sorry that last comment was really hard to read -- I've updated the question so the interface code is readable.
    Jorenko : How are you calling gvf()?
    Jason Sundram : I've updated the question with the calling code (at the bottom). Basically, I'm calling gvf and GetFieldValue() the same way.

Web-Developer's Project Template Directory

IMPORTANT: The accepted answer was accepted post-bounty, not necessarily because I felt it was the best answer.


I find myself doing things over and over when starting new projects. I create a folder, with sub-folders and then copy over some standard items like a css reset file, famfamfam icons, jquery, etc.

This got me thinking what the ideal starting template would be. The reason I'm asking is that I'm going through once again and am wondering what I should include in my template so that I don't have to go back in the future and do this all over again with every new site I start.

What I currently have follows:

Project Template Folder
  • index.html -- XHTML 1.0 Strict Doctype. Meta Tags. CSS/js Files Referenced.
  • css/
    • default.css -- Empty. Reserved for user-styles.
    • 960/ -- 960 Grid System for CSS Layouts.
      • 960.css
      • reset.css
      • text.css
  • js/
    • default.js -- Empty. Reserved for user-scripts.
    • jQuery/ -- Light-Weight Javascript Framework
      • jquery-1.3.1.min.js
  • img/
    • famfamfam/ -- Excellent collection of png icons
      • icons/
        • accept.png
        • add.png
        • ...etc
From stackoverflow
  • I have a similar structure and naming convention but for CSS, I use BluePrint which I find is more extensible. Also prefer jQuery having recently switched from prototype. In addition I have a common.js file that is an extension with custom functions for jQuery.

    A /db/ folder with .sql files containing schema definitions. A /lib/ folder for common middle-tier libraries.

    I will also have a /src/ folder which will sometimes have raw files such as Photoshop templates, readme's, todo lists etc.

    Jonathan Sampson : Excellent idea regarding Photoshop files. I work a lot in PS and usually do have .PSD's littering my desktop from time to time, or littering my project folder.
  • I think the structure is good. The addition of a few other folders depends on what type of work you are completing.

    For freelancing and the like, the addition of PSD folders, client comments would be a nice addition.

  • A very MS skewed view, but my SOP right now is along the lines of:

    • documentation/
      • architecture/ (what you might call code documentation)
      • communications/ (important client docs)
      • spec/
      • whitepapers/
    • graphics/
      • *.psd
    • source/

      • com.mycompany.projectname.solutionA/
      • com.mycompany.projectname.solutionB/
      • com.mycompany.projectname.solutionC/
      • com.mycompany.projectname.solutionX/ (project in the business sense here)

        • businesslogic/
          • *.cs (or whatever)
        • (further projects - in the visual studio sense)
        • site/

          • handlers/ (rarely do I use actual .html these days)
          • modules/
          • resources/

            • img/ (pngs jpegs, gifs whatever)

              • skin/
                • icons/
                • backgrounds/
            • js/ (compressed when published)

              • library/ (standard code)
              • common/ (app specific code)
              • *.js (app specific code, hopefully nil)
            • css/
              • skinX/ (even if there is only "default")
                • extension.css
              • base.css
            • transforms/(always hidden from public by config or build process)
              • *.xslt
        • unittests/
          • mocks/
          • testmain.cs (or whatever)
    • thirdparty/
      • dependencies
  • If you have a lot of projects with a lot of static content in common (e.g. jquery, css framework, etc) make yourself a media server to serve all these. Then, instead of creating a bunch of folder structure from a "template" all you do is include the right files in your project's html. If you really want a template, your template becomes one html file instead of a directory structure.

    This also gives you an easy way to update the static media for your sites (e.g. moving to the next version of 960). you only have to do it in one place. Of course, you still have to make sure that your updates don't break existing sites! :)

    You can make the scheme a bit more complicated if certain projects have overlapping needs but are different from others. Just have a directory at the top level of the server for each setup and to each setup corresponds one html "template". The main idea is to have to deal with only one copy of everything that is common.

    You can certainly do this on a small VM (e.g. linode) for $20/mo or a virtual web-server on your current web server. You don't really need a server, for that matter, you just need a folder. However, I think you can have some significant performance gains by having a dedicated media servers. I'd recommend using a fine-tuned apache or nginx for this purpose.

    As for site-specific static files, it is also a good idea that they live on the media server and the directory structure would probably be exactly what you have, but they would/should be empty directories.

  • I definitely love the idea of having a skeleton template folder like this, but if you use a few different technologies, definitely pay close attention to the structure. My VB.net folder structure has a totally different setup compared to PHP. It sounds like common sense, but I have seen people approach both the same way.

  • My web development framework sits in a git repository. Common code, such as general purpose PHP classes gets developed in the master branch. All work for a particular website gets done on a branch, and then changes that will help in future work get merged back into master.

    This approach works well for me because I have full revision control of all the websites, and if I happen to fix a bug or implement a new feature while working on a branch I can do the merge, and then everything benefits.

    Here's what my template looks like:

    /
    |-.htaccess            //mod_rewrite skeleton
    |-admin/               //custom admin frontend to the CMS
    |-classes/             //common PHP classes
    |-dwoo/                //template system
    |-config/              //configuration files (database, etc)
    |-controllers/         //PHP scripts that handle particular URLs
    |-javascript/
          |-tinyMCE/
          |-jquery/
    |-modules              //these are modules for our custom CMS
          |-news/
          |-mailing_list/
          |-others
    |-private/             //this contains files that won't be uploaded (.fla, .psd, etc)
          |-.htaccess      //just in case it gets uploaded, deny all
    |-templates/           //template source files for dwoo
    
    Thelema : This is a bit heavyweight a solution, I think. Having all websites I've developed in one git tree, and just different branches... I guess if your projects have so much in common, it'd update them all on a utility bugfix.
    MichaelM : The reason I am doing it like that is we have an in house developed CMS that all the sites use, that makes up the majority of the codebase. A more elegant solution would be to have the CMS in its own repo and use git-submodule to clone it into each website's own repo. This will be done eventually ;)
  • At work we use Code Igniter as a PHP framework for our web applications and have created a new project template which does exactly that: Simple directory structure, Blueprint CSS, jQuery and the Code Igniter application folder, filled with a couple of commonly used libraries (Authentication, some speciales models for often used databases...).

    The main motto here is: It's always easier to delete components than to add them. So fill your template up.

    (And when I'm starting a new project in my spare time I sorely miss that template...)

  • I think what you have here is great.... What you've listed is of course all about the public front end of your app. My only addition to this, is to keep all your backend code and source out of the public web space if possible, as the less things you have in the public space, the more secure your app is.

    So I'd suggest you take your entire tree, and put it in:

    httpdocs/(all you had in your project template folder)
    

    then put all your backend code (e.g. php libraries, sql files, etc) in adjacent subdirectories:

    httpdocs/(all you had in your project template folder)
    phplibs/
    sql/
    

    etc.

    And, even for your front end stuff, make sure you don't copy in any example files that may come with your front end libraries, as the examples themselves may have security problems that would allow people to XSS or otherwise compromise your site.

  • I have been using the following setup for a while now with great results:

    • /site: This is where my actual working website will live. I'll install my CMS or platform in this directory after the templates are created.
      • .htaccess (basic tweaks I usually find myself enabling anyway)
      • robots.txt (so I don't forget to disallow items like /admin later)
    • /source: Contains any comps, notes, documents, specifications, etc.

    • /templates: Start here! Create all static templates that will eventually need to be ported into the CMS or framework of /site.

      • /behavior
        • global.js (site-specific code; may be broken out into multiple files as needed)
      • /media: Images, downloadable files, etc. Organized as necessary

      • /style: I prefer modular CSS development so I normally end up with many stylesheet for each unique section of the website. This is cleaned up greatly with Blender - I highly recommend this tool!

        • behavior.css (any styling that requires a JS-enabled browser)
        • print.css (this eventually gets blended, so use @media print)
        • reset.css (Eric Meyer's)
        • screen.css (for @media screen, handheld)
      • /vendor: all 3rd party code (jQuery, shadowbox, etc.)

      • Blendfile.yaml (for Blender; see above)

      • template.html (basic starting template; can be copied and renamed for each unique template)
  • I use a similar layout, but with one major exception: all of these directories live under a top-level media/ directory. This is for a few reasons:

    1. This directory is rsync'd to two other servers which handle all of the static media requests.
    2. Having multiple hosts allows some browsers to make more parallel requests for support files.
    3. The media/ directory has its own .htaccess file which strips off a psuedo directory from the path which is the date-time last modified of the image (or whatever).

    A custom template tag (I have used this with 2 Django projects, but you could do it in PHP, etc.) generates urls which a) semi-randomly choose one of the media servers, b) add the time-based pseudo directory to the path, and c) give the object an Expires time of now + 10 years.

  • I like OPs as a default start point. your standard template should err on simplicity, with the ability to add complexity only if it's needed.

    one addition:

    /robots.txt

selecting top column1 with matching column2

sorry for asking this, but i'm runnin' out of ideas

i have this table:

[id]    [pid]    [vid]
1        4        6844
1        5        6743
2        3        855
2        6        888
...

how to i query this eg.table to get the following result:

[id]    [pid]    [vid]
1        5        6743
2        6        888

i want to get the highest [pid] for an [id] with the [vid] matching to this [pid]

any ideas?

i'm using mssql 2008

From stackoverflow
  • one way

    select t1.* from
    (select id,max(pid) as Maxpid
    from yourtable
    group by id) t2
    join yourtable t1 on t2.id = t1.id
    and t2.Maxpid = t1.pid
    
    Andreas Niedermair : sorry for depriving you the points :) but Bliek's solution is much more comfortable and offers a lot more of options...
  • Since you're using Microsoft SQL Server 2008, then I'd recommend Common Table Expressions and the OVER clause to accomplish dividing the results into groups by id, and returning just the top row in each group (ordered by pid). Bliek's answer shows one way to do that.

    (This same basic approach, by the way, is very useful for more efficient paging, as well.)

    There isn't a fantastically great way to do this with "standard" SQL. The method show in SQLMenace's answer will only work in databases where you can use a subquery as a table. It'd be one way to accomplish this in SQL Server 2000, for example, but may not work in every mainstream RDBMS.

    Andreas Niedermair : sry ... it's mssql 2008
  • I would use Common Table Expressions (CTE). This offers lots of possibilities like so:

    WITH Result (RowNumber, [id], [pid], [vid])
    AS
    (
        SELECT Row_Number() OVER (PARTITION BY [id]
                                  ORDER     BY [vid] DESC)
              ,[id]
              ,[pid]
              ,[vid]
          FROM MyTable
    )
    SELECT [id]
          ,[pid]
          ,[vid]
      FROM Result
     WHERE RowNumber = 1
    
    Andreas Niedermair : as your solution provides more options, i'll give you the point!

In SqlServer 2008, how would I generalize multiple adjacent polygons?

When you have a table with a Geometry type field (or Geography), you can call the Reduce() function to have the shapes reduced in number of vertices. Works very nicely. However, when sevral of the polygons are adjacent (they share parts of their borders), the reduced polygons do not necessarily do so.

Example

The SQL batch:

CREATE TABLE #Shapes (
shape geometry,
naam varchar(50)
 )

-- exact:
insert into #Shapes (naam, shape) VALUES ('Area A',Geometry::STGeomFromText('POLYGON ((52.084744368912652 5.1304192959796637, 52.085234231548384 5.1304194002877921, 52.085474282948049 5.1304486630822, 52.0857341082301 5.1304792705923319, 52.086134375073016 5.1306082883384079, 52.086594087770209 5.13079824927263, 52.087194303050637 5.1311187236569822, 52.089074697112665 5.1323992793913931, 52.089834430487826 5.1333390253130347, 52.090353938518092 5.1341692635323852, 52.090254480473 5.1342997345712416, 52.090824429301414 5.13520842681262, 52.09141399711384 5.1360295349486274, 52.091884278226644 5.1365492835175246, 52.092085719574243 5.1367767199408263, 52.092194211203605 5.1368992186617106, 52.092494247804545 5.1372492032188495, 52.092884057915427 5.13754907634854, 52.093083867570385 5.137679290259257, 52.093254011290028 5.1378082139755827, 52.093554640188813 5.1380093733314425, 52.094204571098089 5.1384683684445918, 52.094214495038614 5.1384888619650155, 52.093702809136488 5.1390791568504124, 52.0939114689827 5.1395669728517532, 52.0938675517682 5.1396009074524045, 52.093849835848111 5.1396084928439114, 52.093797143315896 5.1396473892964423, 52.093789743114428 5.1396500989447063, 52.093731224210721 5.13969055645838, 52.093728204024956 5.1396938753314316, 52.093717452138662 5.1397007238119841, 52.09355255169794 5.139717671321705, 52.093311328208074 5.1395945930853486, 52.093306955655407 5.1395602072316251, 52.093115365831181 5.1400826557073742, 52.093052050564438 5.1401469679549336, 52.092979203676805 5.1401289247442037, 52.092756105586886 5.1398569964803755, 52.092737412561 5.1397823067194368, 52.09235419591127 5.1398883965623128, 52.092214386788811 5.1400686172528616, 52.092164272349919 5.1401695687556135, 52.09208471653983 5.1403786691371351, 52.0920239102561 5.1405293103307486, 52.091924546519294 5.1407297900877893, 52.091534494888037 5.1407990844454616, 52.091654436912947 5.1401591910829172, 52.091713753540262 5.1397284107361845, 52.091763769509271 5.1391488309018314, 52.091774359305148 5.1390583129178058, 52.09170373348757 5.1383788494901648, 52.0907391263172 5.1386201300192624, 52.090711282333359 5.1385075189173222, 52.090718721970916 5.1384486802853644, 52.090745792724192 5.1383893731981516, 52.090758387919244 5.1383728119598793, 52.090776969445869 5.1383237342815846, 52.090780415022657 5.1383173598065737, 52.090745287947357 5.1382717578671873, 52.090742629869759 5.1382662602414895, 52.090704807080328 5.1382211977615952, 52.0906867091544 5.1381677808240056, 52.090701617482885 5.1380081428639635, 52.090564404382455 5.138029116065514, 52.09062412660569 5.1386488282587379, 52.090704361908138 5.1396187201607972, 52.09069472597912 5.1397384563460946, 52.090674098813906 5.1398086878471076, 52.090624484543433 5.1397491229489587, 52.090589968811038 5.1397359627815975, 52.090441891923547 5.140045978827402, 52.090305342804641 5.1400443047750741, 52.0902322656475 5.139729289803654, 52.090199632104486 5.1394877941347659, 52.090188750764355 5.1393666968215257, 52.0902532400633 5.1393868076773792, 52.09003754449077 5.1387802169192582, 52.090024582457204 5.1386965749382565, 52.090020758565515 5.1386840578634292, 52.0900124781623 5.1386172670806785, 52.090003480669111 5.1385827830526978, 52.08999918546494 5.1385372205978728, 52.089985796017572 5.1384773049503565, 52.089996868744493 5.1384535257238895, 52.090046249330044 5.138385351980105, 52.090212456043091 5.1382693609882955, 52.090183896290647 5.1379786310671935, 52.090166853580648 5.1378115779987894, 52.0899735938292 5.137785307597369, 52.089885840192437 5.1377143466379493, 52.08985487697646 5.137671007309109, 52.089845903217793 5.1376524229999632, 52.089844238944352 5.1376464897766709, 52.089850628050044 5.1375868958421052, 52.089852778393364 5.137576853302618, 52.089863699774533 5.1374888862706634, 52.089867451693863 5.1373642447870225, 52.089883847394958 5.1373361134901643, 52.089941705111414 5.1372730266302824, 52.090002277167514 5.1372403032146394, 52.090108146462811 5.1372361269295483, 52.09006458793673 5.1368091938053615, 52.089683820260689 5.1369396857917309, 52.089193989204269 5.1364887236994123, 52.088854428613558 5.1373995044268668, 52.088474480202422 5.1383894786704332, 52.088474343996495 5.1383894337341189, 52.088464433038652 5.1383690948872287, 52.088414154422111 5.13834898790222, 52.088394471909851 5.1383694768883288, 52.0883943233639 5.1383694719988853, 52.08832395415709 5.1382487505018526, 52.087933741509914 5.1377592226490378, 52.087544413445592 5.1372594955892383, 52.087484167695806 5.1372292107739481, 52.087364645209163 5.1372284211684018, 52.0869538753575 5.1372190437554366, 52.085683952551335 5.1372596949804574, 52.085304662585258 5.137269108556211, 52.085084051657141 5.1370588609653955, 52.084904317976907 5.137469710316509, 52.084444417446747 5.1384497439414369, 52.084454428168293 5.1385195698547266, 52.084484005579725 5.1385092278942466, 52.084537888644263 5.1385357407853007, 52.084511198022149 5.1389506391238067, 52.084534639492631 5.1391157133039087, 52.084215438459069 5.139372929232195, 52.084103818604156 5.1389697602953825, 52.083964082412422 5.1391396226827055, 52.083963935496286 5.139139630831778, 52.083883681101725 5.1390291205607355, 52.083994359437455 5.1386593720505784, 52.084013982437057 5.1385892418004318, 52.084053878448593 5.1383293403318735, 52.084054407430678 5.1377297231794907, 52.084053982747719 5.1375283871311694, 52.084063940448686 5.1371387927792966, 52.084070490673184 5.13703247718513, 52.084070608951151 5.1370323959272355, 52.084217049471441 5.1370617711960529, 52.0842700656977 5.1370595147110754, 52.084318579515468 5.1370449147663777, 52.084365648221834 5.137017846536426, 52.084410294202549 5.1369791406907863, 52.084451525192954 5.1369308069453, 52.084497402298688 5.1368615722581685, 52.084511263761669 5.1368357082828879, 52.084539652187722 5.1367929205345337, 52.084559679031372 5.1367565956898034, 52.084580525973493 5.1367251129565776, 52.0845936126653 5.1367018828692963, 52.084593039704487 5.1366802926640958, 52.084593520236 5.1366613829106731, 52.084592797560617 5.136602794053033, 52.0845930285151 5.1365417347624449, 52.084591784281656 5.1365062294062227, 52.084592622431977 5.1364672367903337, 52.084591892315075 5.1364289335906506, 52.084595442516729 5.13633631542325, 52.084596794845957 5.1363224481129421, 52.084599652094766 5.13625919749029, 52.084600140111739 5.1362545876124468, 52.084603969780289 5.1361925578721053, 52.084604394622147 5.1361672168131918, 52.084607248043845 5.1361305358165161, 52.084609296828042 5.13606852098146, 52.084609103156254 5.1360535530839115, 52.084611643842678 5.1360064989442122, 52.08461217648793 5.1359452261162533, 52.084612038685009 5.1359415214974433, 52.084614087827504 5.1358594063203782, 52.084640604443848 5.1355516116600484, 52.084642857778817 5.135543460957706, 52.084982043160878 5.1354961035347806, 52.085083917947486 5.1345288194715977, 52.085104202153161 5.1343492493033409, 52.08524441709433 5.1330996853375064, 52.085165794240311 5.1330994283780456, 52.085158604676472 5.1330777355575146, 52.084887840552256 5.1328501671087, 52.084870130718066 5.1327825202649118, 52.084810143569484 5.132734818616882, 52.084766256157309 5.1326845148578286, 52.084753367166229 5.1326649976350005, 52.084720281418413 5.1326657184399664, 52.084673544857651 5.1326567681971937, 52.084627489326522 5.13263783371076, 52.084616634761915 5.1326309095602483, 52.084607382304966 5.1326056816615164, 52.084589018020779 5.1325388213153929, 52.084566780831665 5.1324195361230522, 52.08455663616769 5.1322953840717673, 52.084555578185245 5.1322289216332138, 52.084558193339035 5.1321669477038085, 52.084565328201279 5.1320932512171566, 52.084573237691075 5.1320388016756624, 52.084590001497418 5.1319514436181635, 52.084614846622571 5.1318454830907285, 52.084674907008818 5.1317076328407039, 52.084733415627852 5.1315451303962618, 52.084768428234277 5.1314570531469457, 52.084772500442341 5.131445026723668, 52.084790059469135 5.1313976899708305, 52.084790684864267 5.1313653332182225, 52.084789962507784 5.1313581170979887, 52.084786229995423 5.1313093374080232, 52.084781658835709 5.1312665985897183, 52.084776584757492 5.131205978570506, 52.084776126593319 5.1311985920700378, 52.084773858077824 5.1311737054493278, 52.084770929767942 5.1311195062007151, 52.084764682454988 5.1310441740788519, 52.084762406875207 5.1310067452953634, 52.084759807214141 5.1309909871779382, 52.084745739819482 5.1308908765204251, 52.084737451048568 5.1308199469931424, 52.084731393493712 5.1307550501078367, 52.084726219235463 5.130682019587562, 52.084717591805187 5.130595849588774, 52.084696356672794 5.1304316397290677, 52.084744368912652 5.1304192959796637))', 1) );
insert into #Shapes (naam,  shape) VALUES ('Area B', Geometry::STGeomFromText('POLYGON ((52.089193944586441 5.1364884474314749, 52.089683880347387 5.1369394774090678, 52.090064640389755 5.1368089618626982, 52.090064767515287 5.13680902402848, 52.090108351781964 5.1372362461406738, 52.0900023451254 5.137240494616317, 52.089941830607358 5.1372731845887953, 52.089884013120034 5.1373362265352416, 52.089867649300196 5.13736428650584, 52.089863897534087 5.1374888976570219, 52.089852973818779 5.1375768855214119, 52.089850827719964 5.1375869208953633, 52.08984444080243 5.1376464707614575, 52.089846089016071 5.1376523461555816, 52.089855048116348 5.13767090524721, 52.089885986401136 5.1377142074887443, 52.089973680692943 5.137785122508185, 52.090167043032125 5.1378114717081189, 52.090184094849974 5.1379786091856658, 52.090212659211829 5.138269433286041, 52.090046387117965 5.1383854977954284, 52.089997038751484 5.1384536319841185, 52.089986001565585 5.1384773087642488, 52.0899993844796 5.138537187827751, 52.090003677353721 5.1385827515141784, 52.0900126749184 5.1386172289494425, 52.090020956756526 5.1386840232833055, 52.0900247762911 5.1386965326964855, 52.090037737332914 5.1387801609122805, 52.090253500966355 5.1393869426101446, 52.090253373142332 5.1393870580941439, 52.09018895904866 5.1393668668649326, 52.09019982968524 5.1394877681651483, 52.090232462748588 5.1397292593531256, 52.090305473417473 5.1400441225035083, 52.090441768325739 5.1400458008552627, 52.0905898406636 5.1397357748355716, 52.090624607168138 5.1397489595692605, 52.090674059544682 5.1398083794509937, 52.090694529374325 5.1397384163970843, 52.090704163346672 5.1396187301667995, 52.0906239267189 5.1386488468750029, 52.090564216952771 5.1380289690569043, 52.090701825218275 5.138007998932153, 52.090686907175666 5.1381677433547006, 52.090704979235063 5.1382210930865915, 52.090742795495316 5.13826614478603, 52.090745454392028 5.1382716438933382, 52.090780634433031 5.138317345874384, 52.090777151606311 5.1383238151729582, 52.090758565347642 5.1383729032240808, 52.090745967798135 5.1383894728374937, 52.090718918413778 5.1384487237036574, 52.09071148235433 5.1385074989634694, 52.090739235906476 5.1386199161658359, 52.091703911079094 5.1383786785881966, 52.091774561209604 5.1390583219472319, 52.091763966455993 5.1391488551129392, 52.091713952366263 5.1397284283302724, 52.091654634801671 5.1401592225302011, 52.091534660555041 5.1407988700928273, 52.091924405223438 5.1407296329252166, 52.092023730557614 5.1405292234111544, 52.092084533682055 5.1403785903667165, 52.092164086876437 5.1401694919914007, 52.092214212752879 5.1400685210246593, 52.092354092746973 5.1398882211651653, 52.092737518250942 5.1397820895072073, 52.092756280866688 5.1398568955139261, 52.092979332917338 5.1401287692562034, 52.093051998862443 5.14014675848039, 52.093115186976668 5.1400825616937738, 52.093306944705546 5.1395597066730261, 52.093307103263214 5.139559774659574, 52.093311476645688 5.1395944439214718, 52.093552575019729 5.1397174675798443, 52.093717376162488 5.1397005364784905, 52.093728081547653 5.1396937158987059, 52.093731097411364 5.1396904007997364, 52.093789641978219 5.1396499255206436, 52.09379703433958 5.139647218074332, 52.093849730910733 5.139608321711421, 52.0938674450952 5.1396007388582916, 52.093911277158938 5.13956686834194, 52.093702596845105 5.1390791060402989, 52.094214342534542 5.1384887341409922, 52.094234085874632 5.1384696427267045, 52.094364419566851 5.1384893088412067, 52.094364145770669 5.1383595434017479, 52.094394268468022 5.1381287302356213, 52.09443390479516 5.138148912037261, 52.094484106955747 5.1381194878988437, 52.094514668919146 5.1380682252347469, 52.094674076435417 5.1382088991813486, 52.095094393635229 5.1384881954232995, 52.0952940530714 5.1385585838544232, 52.095604252303019 5.1385889891535044, 52.095554116032766 5.1386696371579523, 52.095534724403237 5.1388492132525849, 52.095524277190037 5.1390082753444624, 52.095594465266913 5.1390487975440919, 52.095594199141487 5.1393494226504117, 52.09559461963309 5.1399783839006, 52.095604153974683 5.1410990775805754, 52.095644179129778 5.1413294123732438, 52.09575448022224 5.1416396433487535, 52.095824270925078 5.1419194503811445, 52.096084321906162 5.1429293346052836, 52.096143952025322 5.1430793148784755, 52.096264120657 5.1433793206233531, 52.096193926805284 5.1433798011214318, 52.096113997035054 5.14339920294765, 52.096024247104872 5.1434492955148228, 52.095944452364236 5.1435387324349744, 52.095874538511147 5.14362958598761, 52.095844099589421 5.143679338650661, 52.095844470186279 5.1438587997111922, 52.095854729064243 5.1440396906996444, 52.095894579105732 5.1441883100385768, 52.095964113250375 5.144369007088244, 52.09580374216273 5.144229786732418, 52.095674295010134 5.1441983953353239, 52.095563816432822 5.14421941922198, 52.095403983902024 5.1442888717546564, 52.095254029380158 5.1443597327452153, 52.094414402963594 5.1447291097138077, 52.094194360597214 5.1448091029165, 52.093554132385179 5.1451087987516075, 52.09298392268829 5.14536870829761, 52.092384074527615 5.1456389861371825, 52.091314621968991 5.1461291963244005, 52.091214230906282 5.1462493549551356, 52.091174073517323 5.1464188823010772, 52.0911739426665 5.146418813848868, 52.09113409327086 5.1462687528401041, 52.091084660668564 5.146199182483377, 52.091033940669149 5.1464488115161657, 52.090953806928624 5.1464084108564867, 52.090854425442245 5.1464496781230418, 52.089684411417693 5.1471287335734814, 52.0895846124041 5.1471190678897267, 52.088994233263378 5.1476095448153067, 52.088864096673205 5.1477386702317744, 52.088784483494237 5.1475289191585034, 52.088713807872537 5.1472491544173726, 52.088664193741309 5.1471487923554067, 52.088594123489734 5.1471287621828763, 52.088524112701435 5.1471597642893574, 52.088323859963566 5.1472586041782051, 52.088194384938106 5.1472490853630006, 52.088083737995476 5.147229231428355, 52.087984558660537 5.1470896604005247, 52.0871439545881 5.144788873847574, 52.086584153570342 5.1431184258301306, 52.086113808001116 5.1425490758657, 52.085764196002856 5.142129332292825, 52.085273851326242 5.1414594290601263, 52.084604130359367 5.1405483337584883, 52.08448414108716 5.1403388837352395, 52.084363697096705 5.1399091542698443, 52.084215331124142 5.1393728284165263, 52.084534444796994 5.1391156225659822, 52.084510998101905 5.1389506384730339, 52.084537685041475 5.1385358115798789, 52.084483979582181 5.1385094355204064, 52.084454281721264 5.138519779080525, 52.084444217151031 5.1384497005492449, 52.084904137838336 5.1374696237373572, 52.08508396637626 5.1370586035773158, 52.085304709049147 5.1372689084542849, 52.085683944402767 5.1372594968589222, 52.08695387118496 5.1372188439127058, 52.087364651495307 5.1372282228088277, 52.087484228890389 5.137229019543156, 52.087544555542991 5.1372593543492258, 52.087933897256818 5.1377590987963755, 52.088324117939919 5.1382486345246434, 52.088394418613781 5.138369242607296, 52.088414155179635 5.1383487726561725, 52.0884645585902 5.1383689332287759, 52.0884744236222 5.1383891381781037, 52.088854240353591 5.1373994332191018, 52.089193944586441 5.1364884474314749))', 1) );
insert into #Shapes (naam,  shape) VALUES ('Area C', Geometry::STGeomFromText('POLYGON ((52.081104027922265 5.1258389879949391, 52.081314665614627 5.1259588550310582, 52.082414517994039 5.1266395719721913, 52.082954646321014 5.1270186660112813, 52.083513987367041 5.127549389610067, 52.083794155623764 5.1278395495610312, 52.084174386574887 5.1282589976908639, 52.084274505455781 5.1284189013796713, 52.08453426125925 5.1288288246141747, 52.085124507819643 5.1299386160409242, 52.08521465482071 5.1300693768952019, 52.0853342462746 5.1301182725468744, 52.0854241597699 5.1300988405710086, 52.0854743384989 5.1304488354362547, 52.085234220619661 5.130419600171515, 52.084744388967557 5.1304194940048324, 52.08439406089019 5.1305090384557843, 52.083914360133932 5.1306285039224422, 52.083414051565342 5.1307787221157923, 52.082813916262239 5.13094844610896, 52.082724283281529 5.1306586048111562, 52.082483787322417 5.1300093204481527, 52.08225411306649 5.1293789464909949, 52.082194455789093 5.1292188489812043, 52.082134172902443 5.1291885531973094, 52.082084508962 5.1290896165883169, 52.082023798371665 5.1288696515839547, 52.081883911043406 5.1281993770971894, 52.081856097793207 5.12798699515406, 52.081856237724423 5.1279869175050408, 52.082000762340613 5.1280515332473442, 52.082027135184035 5.1280940270517021, 52.0820355968099 5.1281161647869, 52.08205282002023 5.1281410993754166, 52.08213594150827 5.1278323108932256, 52.0820438895719 5.1277594091965328, 52.081953932996839 5.1277496579568833, 52.081884289887846 5.1271693162703134, 52.081813924670755 5.1270196131258938, 52.081552422139794 5.1268787173321471, 52.08152364961375 5.1267665265884057, 52.081485387952739 5.1266524291002371, 52.081442847483068 5.1265567842247837, 52.081396028901857 5.1264795880384764, 52.081344932177927 5.1264208389159505, 52.081293396464417 5.1263833287749234, 52.081279310281388 5.1263776289997622, 52.081249886541627 5.1263603481929749, 52.081222431567454 5.12633884719625, 52.081221418222412 5.1263384295161813, 52.081197269726545 5.126324187265709, 52.081195053295232 5.1263138890499249, 52.081184833077714 5.1262332251062617, 52.0811841667945 5.1261982778874859, 52.081168951815926 5.1261331316782162, 52.081164751928249 5.1260440781433525, 52.081066497950815 5.1259329431923106, 52.081104027922265 5.1258389879949391))', 1) );
insert into #Shapes (naam,  shape) VALUES ('Area D', Geometry::STGeomFromText('POLYGON ((52.084103860426694 5.1389694481622428, 52.084363892148971 5.1399091025981294, 52.084484331319835 5.1403388143996294, 52.084604299141489 5.1405482272725367, 52.08527401345782 5.1414593127556145, 52.085764355740025 5.1421292096101565, 52.086113962111995 5.1425489480607212, 52.086584335425869 5.1431183374952525, 52.087144145466013 5.1447888108543749, 52.087984736636635 5.1470895681108679, 52.088083857744529 5.1472290623707631, 52.088194406595086 5.14724888795369, 52.088323822820605 5.1472584035787792, 52.088524032849818 5.14715958177112, 52.088594117900357 5.1471285563893616, 52.08866433496587 5.1471486398950219, 52.088713997742161 5.1472490890882909, 52.088784678140655 5.1475289016962051, 52.088534413350153 5.1477695436890123, 52.088604030199349 5.1479895326774567, 52.08846407078854 5.1481186849763318, 52.088304384844378 5.1482683648355305, 52.087993860917578 5.1484991029959017, 52.087834112113342 5.1486196045298129, 52.0874739959836 5.1487791088875383, 52.087183827068657 5.1488594498950988, 52.087034655727216 5.1488792099405627, 52.086844170233235 5.1489094072021544, 52.086553779430687 5.1488890685141087, 52.086283983197063 5.1488190072122961, 52.086004210880986 5.148699401849246, 52.085884556407109 5.148648968199268, 52.085783737245947 5.148579464526847, 52.085444359574467 5.1483186569530517, 52.08505431888625 5.147909271530807, 52.085063869832084 5.14774867403321, 52.085103993769735 5.1475894195027649, 52.085123664481678 5.1475485048696683, 52.084903807879783 5.1472594002206034, 52.084644382136524 5.1469792136778958, 52.08418409107253 5.1464885615278035, 52.0837237383239 5.1459687419701368, 52.083234543621856 5.145409702023275, 52.082664410911732 5.1448292277490495, 52.082063829526305 5.1443087360821664, 52.082091124779964 5.1440836547198483, 52.081992223858833 5.1440890550147742, 52.08196270884946 5.14405638189055, 52.081944186007604 5.1439888756722212, 52.08194406144986 5.1439872064089114, 52.08192484639585 5.1439289392437786, 52.081920254660311 5.1439031759941996, 52.081906982464716 5.1438652367796749, 52.081898384261621 5.143827152704362, 52.081886463514792 5.1437939475605585, 52.081860758494884 5.143810536588699, 52.081833417158236 5.1438379039788957, 52.081759569933638 5.14407270308584, 52.0816137263635 5.1439596123534246, 52.081454453474372 5.1438598307431391, 52.081304313847795 5.14384896773845, 52.080264462672268 5.1430187125121805, 52.079664091113955 5.1425989381968975, 52.079524534521624 5.14249899610877, 52.079534315969795 5.1424492821097374, 52.079674492839317 5.1419992103874552, 52.079703816364884 5.1418385940623406, 52.079714205814525 5.141648898134008, 52.079727753764018 5.1414623958989978, 52.080252137147674 5.1417998058748831, 52.08029427562046 5.1417563394152745, 52.080314928898588 5.1417286938522011, 52.0803562682122 5.1416860464960337, 52.080404439009726 5.1416505186352879, 52.080450373701751 5.1416298456024379, 52.080458209152553 5.1416284950795994, 52.080495744477957 5.141600257018581, 52.080541761592031 5.141581037081778, 52.080577370766676 5.1415776146752092, 52.080586124956035 5.1415745182313319, 52.080565002281219 5.1411468000151217, 52.080635850084946 5.1411388639826328, 52.081214110314008 5.1410789246463136, 52.081586783519015 5.1409964717458934, 52.081614242866635 5.1412574960850179, 52.081570835318416 5.1413511682767421, 52.08156742547277 5.1413547724810877, 52.081523078051127 5.1414396720759816, 52.081520885843375 5.1414458907124478, 52.0815235725604 5.1414493722841144, 52.081564587075263 5.1415304632391781, 52.081586116692051 5.1416122366208583, 52.081591385416651 5.1417623861789625, 52.081744097638875 5.1417384068481624, 52.081754462670077 5.14239915706246, 52.081888611945665 5.1424242914485125, 52.081887235166505 5.1422738104593009, 52.081907565006986 5.1422072551213205, 52.081948822597042 5.1421398329548538, 52.081990273194968 5.1420943139491024, 52.082000561989844 5.1420720012392849, 52.082041298272088 5.1420040489174426, 52.08205503895892 5.1419854623652519, 52.082057312844228 5.1419532595345077, 52.082057383609936 5.141936854692176, 52.082061406905325 5.1418724298121266, 52.082061399472877 5.1418698709458113, 52.082065169426741 5.1418023992023132, 52.08206505025737 5.1417857583146542, 52.082067978335544 5.1417265709023923, 52.082068552136519 5.1417210444026873, 52.08207146529282 5.1416510321596576, 52.082074348499624 5.1415691960222105, 52.082074102712795 5.1415587870869786, 52.082077217031589 5.141500341455882, 52.082077142713729 5.1414836310842942, 52.082064611044075 5.1414689618560345, 52.08204338257201 5.1414488023146987, 52.0820095549712 5.1414023755017455, 52.08195383178483 5.1413428048418419, 52.0819458400365 5.1413370133377612, 52.081897551489291 5.141270585100548, 52.081845151958987 5.1412304241675884, 52.081783577566966 5.1409387167077512, 52.082063805446388 5.1408189585007031, 52.082534100375206 5.1404983382591407, 52.082604082068428 5.1404395992867649, 52.082693810134288 5.1403690781753832, 52.083284175475136 5.1398683352445742, 52.083963928950048 5.1391394941752653, 52.084103860426694 5.1389694481622428))', 1) );

select naam, shape, shape.Reduce(0.001) as reducedShape from #Shapes

drop table #Shapes

This returns two sets of polygons. First the unreduced set:

alt text

Then the reduced set:

alt text

These shapes are much simpler and they do have the rough shape correct, but what I would want is to have the border-parts still shared. So they have to be reduced together, in a way.

I think you have to break them up into polylines first (from edge to edge), then Reduce the lines and then reassembling them to polygons again. I have no idea how to do this in T-SQL though.

Any ideas?

Edit: I've accepted alphadaogg's answer. Both current answers weren't entirely covincing to me, but alphadogg has certainly put in the most effort and I really appreciate any sharing of thoughts. So the bounty goes to him.

I will follow-up with a self-answer later if I find a satisfying method.

Follow-up: I e-mailed with Isaac Kunen, Program Manager on the SqlServer Geo team. His helpfull response is below:

Your problem is not at all rare, but it isn't something we directly support: it's an operation that requires knowledge of the topology of your figures, and we don't have anything like this built in. Essentially, you don't want to store separate polygons for each neighborhood. Rather, you want to store curves representing portions of boundaries, and reuse these boundaries for multiple polygons. When you generalize, you generalize the shared boundary, and all dependent polygons are affected.

You could build this yourself---as the posters in the thread you cite hint---but it may be real effort to do so.

I don't know the third-party software you're using, but this is the other option. If you don't want a full-fledged GIS, you could use a package like the FME from Safe Software (http://www.safe.com). The FME doesn't do general-purpose topology, but I believe it has enough functionality to do what you're looking for. See: http://www.safe.com/products/desktop/under-the-hood.php#3b.

I hope this helps.

Cheers,

-Isaac

From stackoverflow
  • Wow, that's a pretty cool set of features.

    Taking a look at some of the other methods available, here are a few ideas that come to mind:

    On the unreduced shapes, use .STIntersects (returns a boolean) and .STIntersection (returns a shape) to find out if and where two shapes intersect.

    For two adjacent map regions, I would assume that .STIntersection should return the line segment that borders both.

    Then you can reduce these line segments and re-assemble the reduced shapes.

    Teun D : Yes, I guess that STIntersection would be part of the solution. Also, taking STBoundary of A and intersecting it with B gives the shared border.
  • I'm not sure how you'd get the "shared" LineStrings from your shapes. Secondly, once you reduce a "subset" of the shape since your endpoints may move from the original and you will not be able to make them match up after reduction.

    The nutshell of what I would do is basically use boolean operations to play with the reduced shapes.

    First, do what you do, namely create a temporary table of reduced shapes (called #ReducedShapes).

    Then, I would create a second temp table and find the areas of overlap (using STIntersection) between all shapes. In this table, I would basically have columns naam1, naam2 and intsec, the last one being of type shape. Something like (untested):

    INSERT INTO #IntSecs(naam1, naam2, intsec)
    SELECT s1.naam, s2.naam, s1.naam.STIntersection(s2.naam)
    FROM #ReducedShapes s1, #ReducedShapes s2 
    WHERE s1.naam.STIntersection(s2.naam) IS NOT NULL
    

    This gets you a list of where pairs of shapes overlap. In fact, you have two rows for each overlap. For example, if A and B overlap you'd have and . I would make a pass and delete one of the two for each occurence.

    Lastly, for each overlap, I would subtract (STDifference) the intersection from only one of the two regions in the pair from the #ReducedShapes table. Imagine you have two squares A and B, half-overlapping. The operation would involve A.STDifference(B) meaning you keep all of B and half of A. I would insert the modified shapes into a third table (say #ModifiedShapes).

    Two problems: a) as you can see from your "orange" and "blue" shapes, they did not reduce similarly, so you'll get one of two possible reductions depending on how you deal with who "wins". b) a more complicated form of the problem is that, depending on the complexity of the initial shapes, you may get overlap between three or more regions. You'll have to determine your own way to establish which one shape "wins" in that intersection, based on your particular needs. It's not clear if there are constraints. Could be as simple as arbitrarily picking a winner by ordering, or more complicated since accuracy is important.

    The above concept unfortunately does not address the issue of gaps. This one's a little more complicated and I am not 100% sure how to resolve it. But, if you create a third table that subtracts (STDifference again) all the modified shapes #ModifiedShapes from all the original shapes in #Shapes (testing for overlap before actually subtracting, of course), you'd be left with the remainder shapes in the gaps. You'd want to aggregate the adjoining shapes and assign a "winning color", possibly merging it back in with the related shape.

    This answer is long and I will leave it like this. I may be barking up the wrong tree. Based on your feedback/questions, I would add to the post.

    Teun D : Thanks for these ideas. A different approach from what I had in mind. Very interesting. The problems with gaps and multiple overlaps are serious though. I think that "more than double overlaps" can be solved by adding the overlap always to the lowest ID shape. Gapsseems tougher.
    alphadogg : Overlaps are hard because there are multiple ways to address them. But, I didn't know what your needs were. The easiest is to let one region win.
    alphadogg : And, yes, gaps are much, much harder. The idea is to end up with a set of shapes for each gap, assign each one a color of a neighboring region and then merge it into that region. Not exactly sure how...
    alphadogg : Maybe found it? Consider STInteriorRingN() on the STUnion() of all modded shapes. It should give you a GeomCollection of gaps. Then, armed with this list, find the areas in the gap from the original, unreduced shapes and pick a winner for each gap.
    alphadogg : http://jasonfollas.com/blog/archive/2008/04/03/sql-server-2008-spatial-data-part-4.aspx
    Teun D : Yes, that could work. Although a gap might be "open ended". Haveing no bordering polygon on on side. There is no such case in the sample shown, but it could happen.
    alphadogg : Actually, I think we've establsihed how to handle overlaps of reduced shapes. Now, you want to take care of the gaps inside your reduced shapes. If there is an "open gap", like a bay or indentation, then you don't really have to worry about it since it would stay as-is.
    alphadogg : What could happen is that some inside gap is near the edge, such that it looks enclosed but isn't. Then, you'd have a bad inside shape. This would depend on your geo data's quality...
  • An older question I know, but...

    Isaac is right that you could reduce the features to lines, and use them as shared boundaries.

    But the software he mentions - FME - has a transformer called the Generalizer which will simplify them as you wish while still retaining them as polygons. The option to use is called 'Preserve Shared Boundaries'. You can download FME from here and request a 14-day eval license to try it out.

    Cheers

    Mark

    Mark Ireland | FME Evangelist Safe Software Inc.

Sharing authentication between IIS applications on same domain

Hi,

I have an IIS website on www.example.com

and a virtual directory at www.example.com/demo/

How can I use the authentication cookie from www.example.com in my virtual directory?

From stackoverflow
  • You are looking for a Single Site Login solution. If the article I linked to doesn't help you, there's plenty more on google when you know what to search for ;)

  • A solution would be to use integrated authentication. This way the user look up, and authentication authority used, will be the same accost all sites with the servers on the same domain. If you are using something like basic or kerberos authentication then your authentication will not pass between sites even on the same server and possibly between parts of the site that run under different threads, eg a different app pool.

    Use session data in asp or cookies to share session information on the same site between pages. Cookies will work even if the virtual folders are shared in a different pool. Just code around the requirements of your virtual directory, in case its shared between multiple sites.

    P.S. If you are already using cookies, just have the code in your virtual be the same as what you are using on the other pages.

    What are the additional requirements for the virtual? Is it on the same server?

    Robert Koritnik : What if the main website web application uses forms authentication?
  • The cookies are shared in the same domain, even shared between applications. I have used the same cookie to share authentication between a Classic ASP app and a .net app without problems.

    Just use the same rules to encrypt or store the cookie.

padding making links not work?

The link only works when i click on the actual text not the area around it even though the hover effect is working so i know the button is being targeted?

this is also happening on a list within the site where I'm using left-padding and placing images there, if i click where the padding is it doesn't work?

could .js scripts effect this, it all for a lightbox I'm using

Any ideas??

ul#navigation { 
  list-style-type: none;
  margin: 0;
  padding: 0;
  padding: 0;
  }

ul#navigation li a {
  position: absolute;
  bottom: 10px; 
  display: block;
  width: 5em;
  padding: .5em 0;
  color: #FFF;
  background: #92da3a;
  text-align: center;
  text-decoration: none;
  font-size: 11px; 
  }

ul#navigation li a:hover {
  color: #05554f;
  }

ul#navigation .back {
  float: left;
  width: 4em;
  padding: 10px;
  }

ul#navigation .close {
  float: right;
  width: 4em;
  padding: 10px;
  }

ul#navigation li.mt {
  border-bottom: 2px solid #92da3a; 
  width: 480px; 
  position: absolute; bottom: 30px; left: 20px;
  }

Many thanks :)

From stackoverflow
  • Off the top of my head, I'm thinking to render each as a element instead, then setting the span's onclick event to follow the link and putting whatever spaces and text you want within the span ( ).

    window.location = "URL!"
    
  • There is nothing wrong with the CSS for ul#navigation li a. I have copied your CSS to a working example and this appears to function correctly in FF3, IE7 and Chrome.

    I wouldn't expect a (well written) piece of JavaScript to be interfering with your links in any way. Although, in general, a given piece of unknown JavaScript could be doing anything.

    You have too many factors influencing the final rendering and behaviour to determine what may be the cause. You will need to start with a bare minimum and re-add all relevant factors until it breaks, or until everything is re-added and working correctly.

    • start with a (validating) plain (X)HTML document
    • add the relevant CSS to get the link styling you desire
    • add back the rest of the CSS, possibly piece-by-piece if some other CSS rules are interfering
    • add back your JavaScript, again piece-by-piece where relevant

    After this process you should have a more clear idea of what factor is causing the undesired behaviour.

    I'd recommend using the FireFox web developer toolbar to examine what CSS rules are being applied to your navigation links. You may find some other loosely-specified rules are interfering in otherwise unexpected ways.

    You should also confirm your markup and CSS are valid - you can't accurately determine the correct output when dealing with invalid input.

    John McFarlane : Thanks, a very detailed answer, many thanks and i will look into this and post an update.
    Jon Cram : Great. Please do post back an update - I'm quite curious what might be the cause!
  • Let me guess, IE6?

    You really need to specify the browser here with the issue, because there can be vast differneces between different rendering engines. Usually IE6 vs everyone else, with Safari and Opera adding their salt.

    To answer your question, in IE6 sometimes the cursor does not show the "hand" icon, however clicking the area will trigger the link. In that case adding a "cursor:hand" (or whatever it was, looku pthe css property), will fix that for IE6.

  • Id try setting the the UL or LI to position relative, considering you have the A set to position: absolute;

    Having this set may be causing some wierdness.

    If you can also supply the HTML you are using, that will help nail down the issue.

XSLT - How to select XML Attribute by Attribute?

Hello, this is the structure of my source xml:

<root>
<DataSet Value="A">
<Data Value1="1" Value2="anythingA1" />
<Data Value1="2" Value2="anythingA2" />
<Data Value1="3" Value2="anythingA3" />
<Data Value1="4" Value2="anythingA4" />
<Data Value1="5" Value2="anythingA5" />
</DataSet>
</root>

from which I like to create some variables e.g. from all with Value1="2" and all with Value1="5" should result myVar1 with anythingA2 and myVar2 with anythingA5

My approch looks like this

<xsl:variable name="myVarA" select="/DataSet/Data/[@Value1='2']/@Value2" />

but of course is not working since Value2 is no child of Value1.

thanks for any hints in advance!

From stackoverflow
  • Just remove the slash after Data and prepend the root:

    <xsl:variable name="myVarA" select="/root/DataSet/Data[@Value1='2']/@Value2"/>
    
    Andrew Hare : -1 this does not work without the root node
    phihag : @Andrew Hare: Corrected. Thanks to Quassnoi for elaborating, I lost connection immediately after posting the first revision.
    Jeff Yates : added +1 and sacrificed a goat
    spoulson : +1 and did a little jig
  • There are two problems with your xpath - first you need to remove the child selector from after Data like phihag mentioned. Also you forgot to include root in your xpath. Here is what you want to do:

    select="/root/DataSet/Data[@Value1='2']/@Value2"
    
  • Try this

    xsl:variable name="myVarA" select="//DataSet/Data[@Value1='2']/@Value2" />
    

    The '//' will search for DataSet at any depth

  • sometimes its so easy, thanks a lot!

  • I would do it by creating a variable that points to the nodes that have the proper value in Value1 then referring to t

    <xsl:variable name="myVarANode" select="root//DataSet/Data[@Value1='2']" />
    <xsl:value-of select="$myVarANode/@Value2"/>
    

    Everyone else's answers are right too - more right in fact since I didn't notice the extra slash in your XPATH that would mess things up. Still, this will also work , and might work for different things, so keep this method in your toolbox.

  • Note: using // at the beginning of the xpath is a bit CPU intensitve -- it will search every node for a match. Using a more specific path, such as /root/DataSet will create a faster query.