why does read barrier can causes all effects prior to storage from another cpu be perceptible? - concurrency

Documentation about memory barriers of linux kernel(https://www.kernel.org/doc/Documentation/memory-barriers.txt) has this example to illustrate the read barrier in the SMP case can be used to causes all effects prior to storage from another cpu be perceptible.
why dose read barrier can do that?
+-------+ : : : :
| | +------+ +-------+
| |------>| A=1 |------ --->| A->0 |
| | +------+ \ +-------+
| CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
| | +------+ | +-------+
| |------>| B=2 |--- | : :
| | +------+ \ | : : +-------+
+-------+ : : \ | +-------+ | |
---------->| B->2 |------>| |
| +-------+ | CPU 2 |
| : : | |
| : : | |
At this point the read ----> \ rrrrrrrrrrrrrrrrr | |
barrier causes all effects \ +-------+ | |
prior to the storage of B ---->| A->1 |------>| |
to be perceptible to CPU 2 +-------+ | |
: : +-------+

Related

Is there a general set of instructions to swap adjacent and non-adjacent records in a linked list?`

With a singly linked list, swapping non-adjacent cells can be described by the following operation, assuming '=>' means 'now links to':
Y => X->next
X => Y->next
BeforeY => X
BeforeX => Y
However, this operation does not work for swapping adjacent records, creating circular links, as X->next (say) will be Y.
Adjacent record swaps, assuming X is before Y, can be described by a separate set of operations:
X => Y->next
Y => X
BeforeX => Y
I can't seem to solve this set of operations as a subset of the previous set or common children of a parent set.
Is there a uniform, unconditional set of operations that describes a swap that works for both adjacent and non-adjacent records?
Here is some ASCII Art for the two scenarios.
Non-adjacent X and Y
X can come before or after Y in the list as long as there is at least one element between X and Y (so Ax and By could identify the same node when X comes before Y). The situation before:
Bx X Ax By Y Ay
+----+ +----+ +----+ +----+ +----+ +----+
| | | | | | | | | | | |
-->| |-->| |-->| |--...->| |-->| |-->| |-->
| | | | | | | | | | | |
+----+ +----+ +----+ +----+ +----+ +----+
The situation after:
Bx X Ax By Y Ay
+------------------------------+
| |
+------------------------------+ |
| | | |
+----+ | +----+ | +----+ +----+ | +----+ | +----+
| |-+ | |-+ | | | | +>| | +>| |
-->| #| | #| | |--...->| #| | #| | |-->
| | +>| | +>| | | |-+ | |-+ | |
+----+ | +----+ | +----+ +----+ | +----+ | +----+
| | | |
+------------------------------+ |
| |
+------------------------------+
The 4 'next' pointers marked with # are changed.
Before:
Bx->next = X
X->next = Ax
By->next = Y
Y->next = Ay
After:
Bx->next = Y
Y->next = Ax
By->next = X
X->next = Ay
Adjacent X and Y
Assume X immediately precedes Y. The situation before:
Bx X Ax
By Y Ay
+----+ +----+ +----+ +----+
| | | | | | | |
-->| |---->| |---->| |---->| |-->
| | | | | | | |
+----+ +----+ +----+ +----+
The situation after:
Bx X Ax
By Y Ay
+------------+
| |
+----+ | +----+ | +----+ +----+
| |-+ | | +>| | | |
-->| #| | #| | #| | |-->
| | +>| |-+ | |-+ +>| |
+----+ | +----+ | +----+ | | +----+
| | | |
+-------------------+ |
| |
+------------+
Before:
Bx->next = X
X->next = Ax = Y
By->next = Y
Y->next = Ay
After:
Bx->next = Y
Y->next = X # Different
By->next = Ay # Different
X->next = Ay
The result values in the pointers are different, as shown. This means that there isn't a single mapping that works for both the "non-adjacent X and Y" and the "adjacent X and Y" cases — the pointer twizzling must be different.

difference between size_t (*B)[N] and size_t *B[N]

what's the difference between these two lines of code in c++?
size_t (*B)[N] = new size_t[N][N]; and
size_t *B[N] = new size_t[N][N];
first one compiles correctly but with second line, g++ gives this error
matrixim.cpp:43:20: error: array must be initialized with a brace-enclosed initializer
43 | size_t *B[N] = new size_t[N][N];
size_t *B[N]
Here, B is an array of N pointers to size_t
size_t (*B)[N]
Here, B is a pointer to an array of N size_ts
Both of these constructs could be used to create something approximating a 2-dimensional array, but their layout in memory is very different.
size_t *B[N] would look something like this:
B +-------------+-------------+-----+-------------+
+--------+ | B[0][0] | B[0][1] | ... | B[0][N-1] |
| B[0] +--->+-------------+-------------+-----+-------------+
+--------+
| B[1] +--->+-------------+-------------+-----+-------------+
+--------+ | B[1][0] | B[1][1] | ... | B[1][N-1] |
| | +-------------+-------------+-----+-------------+
| ... |
| |
+--------+
| B[N-1] +--->+-------------+-------------+-----+-------------+
+--------+ | B[N-1][0] | B[N-1][1] | ... | B[N-1][N-1] |
+-------------+-------------+-----+-------------+
B is an array of N pointers to size_t, each of which points to the first element of an array of N size_t.
size_t (*B)[N] would look something like this:
B +---------------------------------------------------+
+----+ | B[0] |
| +--->+ +-------------+-------------+-----+-------------+ |
+----+ | | B[0][0] | B[0][1] | ... | B[0][N-1] | |
| +-------------+-------------+-----+-------------+ |
+---------------------------------------------------+
| B[1] |
| +-------------+-------------+-----+-------------+ |
| | B[1][0] | B[1][1] | ... | B[1][N-1] | |
| +-------------+-------------+-----+-------------+ |
+---------------------------------------------------+
| |
| ... |
| |
+---------------------------------------------------+
| B[N-1] |
| +-------------+-------------+-----+-------------+ |
| | B[N-1][0] | B[N-1][1] | ... | B[N-1][N-1] | |
| +-------------+-------------+-----+-------------+ |
+---------------------------------------------------+
Here, B is a pointer to the first element of an array of N arrays of N size_t.

The bean 'AmazonEc2InstanceDataPropertySourcePostProcessor', defined in null, could not be registered

I try to migrate spring from 1.5.7 version to 2.1.5 and this exception occurred.
The stack trace listed below.
2020-02-18 07:23:02.056 INFO 1 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://localhost:8888
2020-02-18 07:23:02.226 INFO 1 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Connect Timeout Exception on Url - http://localhost:8888. Will be trying the next url if available
2020-02-18 07:23:02.226 WARN 1 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://localhost:8888/application/dockerEE,solrWriterEnabled,writerBatchSize5000,aws_integration3a,commondb,neo,reviewModelIndexingDisabled/aws_integration3a": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)
2020-02-18 07:23:02.229 INFO 1 --- [ main] c.j.itemdiscovery.index.Application : The following profiles are active: dockerEE,solrWriterEnabled,writerBatchSize5000,aws_integration3a,commondb,neo,reviewModelIndexingDisabled
2020-02-18 07:23:03.480 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
2020-02-18 07:23:03.510 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 23ms. Found 0 repository interfaces.
2020-02-18 07:23:03.515 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
2020-02-18 07:23:03.520 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 5ms. Found 0 repository interfaces.
2020-02-18 07:23:03.575 WARN 1 --- [ main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'AmazonEc2InstanceDataPropertySourcePostProcessor' defined in null: Cannot register bean definition [Generic bean: class [org.springframework.cloud.aws.context.config.AmazonEc2InstanceDataPropertySourcePostProcessor]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] for bean 'AmazonEc2InstanceDataPropertySourcePostProcessor': There is already [Generic bean: class [org.springframework.cloud.aws.context.config.AmazonEc2InstanceDataPropertySourcePostProcessor]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] bound.
2020-02-18 07:23:03.589 INFO 1 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-02-18 07:23:03.593 ERROR 1 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'AmazonEc2InstanceDataPropertySourcePostProcessor', defined in null, could not be registered. A bean with that name has already been defined in null and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
This is gradle properties of indexer project
apply plugin: 'application'
apply plugin: 'org.springframework.boot'
configurations {
compile.exclude module: 'spring-boot-starter-tomcat'
compile.exclude module: 'slf4j-log4j12'
compile.exclude module: 'log4j-slf4j-impl'
compile.exclude module: 'jms-api'
compile.exclude module: 'tibjms'
compile.exclude module: 'spring-jms'
compile.extendsFrom(springBootCommon, springCloudCommon)
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
dependencies {
dependencySet(group: 'org.apache.solr', version: '6.4.1') {
entry 'solr-solrj'
}
}
}
dependencies {
compile project(':tdm-integration-common')
compileOnly 'org.projectlombok:lombok'
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile group: 'com.tngtech.java', name: 'junit-dataprovider', version: '1.12.0'
testCompile group: 'org.mockito', name: 'mockito-all', version: '1.10.19'
}
Dependencies tree
compileClasspath - Compile classpath for source set 'main'.
+--- project :tdm-integration-common
| +--- com.dig.platform:cassandra:2.1.16
| | +--- com.datastax.dse:dse-java-driver-core:1.8.1
| | | +--- io.netty:netty-handler:4.0.56.Final -> 4.1.36.Final
| | | | +--- io.netty:netty-common:4.1.36.Final
| | | | +--- io.netty:netty-buffer:4.1.36.Final
| | | | | \--- io.netty:netty-common:4.1.36.Final
| | | | +--- io.netty:netty-transport:4.1.36.Final
| | | | | +--- io.netty:netty-common:4.1.36.Final
| | | | | +--- io.netty:netty-buffer:4.1.36.Final (*)
| | | | | \--- io.netty:netty-resolver:4.1.36.Final
| | | | | \--- io.netty:netty-common:4.1.36.Final
| | | | \--- io.netty:netty-codec:4.1.36.Final
| | | | +--- io.netty:netty-common:4.1.36.Final
| | | | +--- io.netty:netty-buffer:4.1.36.Final (*)
| | | | \--- io.netty:netty-transport:4.1.36.Final (*)
| | | +--- com.google.guava:guava:19.0
| | | +--- io.dropwizard.metrics:metrics-core:3.2.2 -> 3.1.2
| | | | \--- org.slf4j:slf4j-api:1.7.7 -> 1.7.26
| | | +--- org.slf4j:slf4j-api:1.7.25 -> 1.7.26
| | | +--- com.github.jnr:jnr-ffi:2.1.7
| | | | +--- com.github.jnr:jffi:1.2.16
| | | | +--- org.ow2.asm:asm:5.0.3
| | | | +--- org.ow2.asm:asm-commons:5.0.3
| | | | | \--- org.ow2.asm:asm-tree:5.0.3
| | | | | \--- org.ow2.asm:asm:5.0.3
| | | | +--- org.ow2.asm:asm-analysis:5.0.3
| | | | | \--- org.ow2.asm:asm-tree:5.0.3 (*)
| | | | +--- org.ow2.asm:asm-tree:5.0.3 (*)
| | | | +--- org.ow2.asm:asm-util:5.0.3
| | | | | \--- org.ow2.asm:asm-tree:5.0.3 (*)
| | | | \--- com.github.jnr:jnr-x86asm:1.0.2
| | | \--- com.github.jnr:jnr-posix:3.0.44
| | | +--- com.github.jnr:jnr-ffi:2.1.7 (*)
| | | \--- com.github.jnr:jnr-constants:0.9.9
| | +--- com.google.guava:guava:19.0
| | +--- org.springframework.data:spring-data-cassandra:2.1.5.RELEASE -> 2.1.8.RELEASE
| | | +--- org.springframework:spring-context:5.1.7.RELEASE
| | | | +--- org.springframework:spring-aop:5.1.7.RELEASE
| | | | | +--- org.springframework:spring-beans:5.1.7.RELEASE
| | | | | | \--- org.springframework:spring-core:5.1.7.RELEASE
| | | | | | \--- org.springframework:spring-jcl:5.1.7.RELEASE
| | | | | \--- org.springframework:spring-core:5.1.7.RELEASE (*)
| | | | +--- org.springframework:spring-beans:5.1.7.RELEASE (*)
| | | | +--- org.springframework:spring-core:5.1.7.RELEASE (*)
| | | | \--- org.springframework:spring-expression:5.1.7.RELEASE
| | | | \--- org.springframework:spring-core:5.1.7.RELEASE (*)
| | | +--- org.springframework:spring-beans:5.1.7.RELEASE (*)
| | | +--- org.springframework:spring-core:5.1.7.RELEASE (*)
| | | +--- org.springframework:spring-tx:5.1.7.RELEASE
| | | | +--- org.springframework:spring-beans:5.1.7.RELEASE (*)
| | | | \--- org.springframework:spring-core:5.1.7.RELEASE (*)
| | | +--- org.springframework:spring-expression:5.1.7.RELEASE (*)
| | | +--- org.springframework.data:spring-data-commons:2.1.8.RELEASE
| | | | +--- org.springframework:spring-core:5.1.7.RELEASE (*)
| | | | +--- org.springframework:spring-beans:5.1.7.RELEASE (*)
| | | | \--- org.slf4j:slf4j-api:1.7.26
| | | \--- org.slf4j:slf4j-api:1.7.26
| | \--- org.projectlombok:lombok:1.16.12 -> 1.18.8
| +--- com.dig.platform:metrics:2.1.16
| | +--- org.springframework.boot:spring-boot-starter-actuator:2.1.5.RELEASE
| | | +--- org.springframework.boot:spring-boot-starter:2.1.5.RELEASE
| | | | +--- org.springframework.boot:spring-boot:2.1.5.RELEASE
| | | | | +--- org.springframework:spring-core:5.1.7.RELEASE (*)
| | | | | \--- org.springframework:spring-context:5.1.7.RELEASE (*)
| | | | +--- org.springframework.boot:spring-boot-autoconfigure:2.1.5.RELEASE
| | | | | \--- org.springframework.boot:spring-boot:2.1.5.RELEASE (*)
| | | | +--- org.springframework.boot:spring-boot-starter-logging:2.1.5.RELEASE
| | | | | +--- ch.qos.logback:logback-classic:1.2.3
| | | | | | +--- ch.qos.logback:logback-core:1.2.3
| | | | | | \--- org.slf4j:slf4j-api:1.7.25 -> 1.7.26
| | | | | +--- org.apache.logging.log4j:log4j-to-slf4j:2.11.2
| | | | | | +--- org.slf4j:slf4j-api:1.7.25 -> 1.7.26
| | | | | | \--- org.apache.logging.log4j:log4j-api:2.11.2
| | | | | \--- org.slf4j:jul-to-slf4j:1.7.26
| | | | | \--- org.slf4j:slf4j-api:1.7.26
| | | | +--- javax.annotation:javax.annotation-api:1.3.2
| | | | \--- org.springframework:spring-core:5.1.7.RELEASE (*)
| | | +--- org.springframework.boot:spring-boot-actuator-autoconfigure:2.1.5.RELEASE
| | | | +--- org.springframework.boot:spring-boot-actuator:2.1.5.RELEASE
| | | | | \--- org.springframework.boot:spring-boot:2.1.5.RELEASE (*)
| | | | +--- org.springframework.boot:spring-boot-autoconfigure:2.1.5.RELEASE (*)
| | | | +--- com.fasterxml.jackson.core:jackson-databind:2.9.8
| | | | | +--- com.fasterxml.jackson.core:jackson-annotations:2.9.0
| | | | | \--- com.fasterxml.jackson.core:jackson-core:2.9.8
| | | | +--- org.springframework:spring-core:5.1.7.RELEASE (*)
| | | | \--- org.springframework:spring-context:5.1.7.RELEASE (*)
| | | \--- io.micrometer:micrometer-core:1.1.4
| | | +--- org.hdrhistogram:HdrHistogram:2.1.9
| | | \--- org.latencyutils:LatencyUtils:2.0.3
| | +--- org.springframework.cloud:spring-cloud-config-client:2.1.1.RELEASE
| | | +--- org.springframework.boot:spring-boot-autoconfigure:2.1.3.RELEASE -> 2.1.5.RELEASE (*)
| | | +--- org.springframework.cloud:spring-cloud-commons:2.1.1.RELEASE
| | | | \--- org.springframework.security:spring-security-crypto:5.1.4.RELEASE -> 5.1.5.RELEASE
| | | +--- org.springframework.cloud:spring-cloud-context:2.1.1.RELEASE
| | | | \--- org.springframework.security:spring-security-crypto:5.1.4.RELEASE -> 5.1.5.RELEASE
| | | +--- org.springframework:spring-web:5.1.5.RELEASE -> 5.1.7.RELEASE
| | | | +--- org.springframework:spring-beans:5.1.7.RELEASE (*)
| | | | \--- org.springframework:spring-core:5.1.7.RELEASE (*)
| | | +--- com.fasterxml.jackson.core:jackson-annotations:2.9.0
| | | \--- com.fasterxml.jackson.core:jackson-databind:2.9.8 (*)
| | \--- io.micrometer:micrometer-registry-prometheus:1.1.2 -> 1.1.4
| | +--- io.micrometer:micrometer-core:1.1.4 (*)
| | \--- io.prometheus:simpleclient_common:0.5.0
| | \--- io.prometheus:simpleclient:0.5.0
| +--- com.dig.platform:feature-logging-logback:1.9.20
| | \--- ch.qos.logback:logback-classic:1.1.7 -> 1.2.3 (*)
| +--- org.springframework:spring-context:5.1.7.RELEASE (*)
| +--- com.datastax.dse:dse-java-driver-mapping:1.8.1
| | +--- com.datastax.dse:dse-java-driver-core:1.8.1 (*)
| | +--- com.google.guava:guava:19.0
| | \--- org.slf4j:slf4j-api:1.7.25 -> 1.7.26
| +--- com.datastax.dse:dse-java-driver-extras:1.8.1
| | +--- com.datastax.dse:dse-java-driver-core:1.8.1 (*)
| | \--- com.google.guava:guava:19.0
| +--- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.8.6 -> 2.9.8
| | +--- org.yaml:snakeyaml:1.23
| | \--- com.fasterxml.jackson.core:jackson-core:2.9.8
| +--- com.fasterxml.jackson.core:jackson-databind:2.8.6 -> 2.9.8 (*)
| +--- com.fasterxml.jackson.core:jackson-core:2.8.6 -> 2.9.8
| +--- com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.8.6 -> 2.9.8
| | +--- com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:2.9.8
| | | +--- com.fasterxml.jackson.core:jackson-core:2.9.8
| | | \--- com.fasterxml.jackson.core:jackson-databind:2.9.8 (*)
| | \--- com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.9.8
| | +--- com.fasterxml.jackson.core:jackson-annotations:2.9.0
| | +--- com.fasterxml.jackson.core:jackson-core:2.9.8
| | \--- com.fasterxml.jackson.core:jackson-databind:2.9.8 (*)
| +--- com.google.code.gson:gson:2.8.0 -> 2.8.5
| +--- org.json:json:20180130
| +--- org.apache.cxf:cxf-core:3.1.12
| | +--- org.codehaus.woodstox:woodstox-core-asl:4.4.1
| | | \--- org.codehaus.woodstox:stax2-api:3.1.4
| | \--- org.apache.ws.xmlschema:xmlschema-core:2.2.2
| +--- org.apache.cxf:cxf-rt-rs-client:3.1.12
| | +--- org.apache.cxf:cxf-rt-transports-http:3.1.12
| | | \--- org.apache.cxf:cxf-core:3.1.12 (*)
| | +--- org.apache.cxf:cxf-core:3.1.12 (*)
| | \--- org.apache.cxf:cxf-rt-frontend-jaxrs:3.1.12
| | +--- org.apache.cxf:cxf-core:3.1.12 (*)
| | +--- javax.ws.rs:javax.ws.rs-api:2.0.1
| | +--- javax.annotation:javax.annotation-api:1.2 -> 1.3.2
| | \--- org.apache.cxf:cxf-rt-transports-http:3.1.12 (*)
| +--- org.apache.cxf:cxf-rt-transports-http-hc:3.1.12
| | +--- org.apache.cxf:cxf-core:3.1.12 (*)
| | +--- org.apache.cxf:cxf-rt-transports-http:3.1.12 (*)
| | +--- org.slf4j:slf4j-api:1.7.24 -> 1.7.26
| | +--- org.slf4j:jcl-over-slf4j:1.7.24 -> 1.7.26
| | | \--- org.slf4j:slf4j-api:1.7.26
| | +--- org.apache.httpcomponents:httpcore-nio:4.4.6 -> 4.4.11
| | | \--- org.apache.httpcomponents:httpcore:4.4.11
| | \--- org.apache.httpcomponents:httpasyncclient:4.1.3 -> 4.1.4
| | +--- org.apache.httpcomponents:httpcore:4.4.10 -> 4.4.11
| | +--- org.apache.httpcomponents:httpcore-nio:4.4.10 -> 4.4.11 (*)
| | \--- org.apache.httpcomponents:httpclient:4.5.6 -> 4.5.8
| | +--- org.apache.httpcomponents:httpcore:4.4.11
| | \--- commons-codec:commons-codec:1.11
| +--- org.apache.cxf:cxf-rt-frontend-jaxrs:3.1.12 (*)
| +--- com.amazonaws:aws-java-sdk-s3:1.11.180 -> 1.11.415
| | +--- com.amazonaws:aws-java-sdk-kms:1.11.415
| | | +--- com.amazonaws:aws-java-sdk-core:1.11.415
| | | | +--- org.apache.httpcomponents:httpclient:4.5.5 -> 4.5.8 (*)
| | | | +--- software.amazon.ion:ion-java:1.0.2
| | | | +--- com.fasterxml.jackson.core:jackson-databind:2.6.7.1 -> 2.9.8 (*)
| | | | +--- com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.6.7 -> 2.9.8
| | | | | \--- com.fasterxml.jackson.core:jackson-core:2.9.8
| | | | \--- joda-time:joda-time:2.8.1 -> 2.10.2
| | | \--- com.amazonaws:jmespath-java:1.11.415
| | | \--- com.fasterxml.jackson.core:jackson-databind:2.6.7.1 -> 2.9.8 (*)
| | +--- com.amazonaws:aws-java-sdk-core:1.11.415 (*)
| | \--- com.amazonaws:jmespath-java:1.11.415 (*)
| +--- com.amazonaws:aws-java-sdk-core:1.11.180 -> 1.11.415 (*)
| +--- javax.jms:javax.jms-api:2.0.1
| +--- org.apache.solr:solr-solrj:6.4.1
| | +--- commons-io:commons-io:2.5
| | +--- org.apache.httpcomponents:httpclient:4.4.1 -> 4.5.8 (*)
| | +--- org.apache.httpcomponents:httpcore:4.4.1 -> 4.4.11
| | +--- org.apache.httpcomponents:httpmime:4.4.1 -> 4.5.8
| | +--- org.apache.zookeeper:zookeeper:3.4.6
| | +--- org.codehaus.woodstox:stax2-api:3.1.4
| | +--- org.codehaus.woodstox:woodstox-core-asl:4.4.1 (*)
| | +--- org.noggit:noggit:0.6
| | +--- org.slf4j:jcl-over-slf4j:1.7.7 -> 1.7.26 (*)
| | \--- org.slf4j:slf4j-api:1.7.7 -> 1.7.26
| +--- commons-codec:commons-codec:1.10 -> 1.11
| +--- commons-io:commons-io:2.5
| +--- org.apache.commons:commons-lang3:3.9 -> 3.8.1
| \--- org.hibernate:hibernate-validator:6.0.10.Final
| \--- org.hibernate.validator:hibernate-validator:6.0.10.Final -> 6.0.16.Final
| +--- javax.validation:validation-api:2.0.1.Final
| +--- org.jboss.logging:jboss-logging:3.3.2.Final
| \--- com.fasterxml:classmate:1.3.4 -> 1.4.0
+--- io.dropwizard.metrics:metrics-core:3.1.2 (*)
+--- org.projectlombok:lombok -> 1.18.8
+--- org.springframework.boot:spring-boot-starter-actuator -> 2.1.5.RELEASE (*)
+--- org.springframework.boot:spring-boot-starter-security -> 2.1.5.RELEASE
| +--- org.springframework.boot:spring-boot-starter:2.1.5.RELEASE (*)
| +--- org.springframework:spring-aop:5.1.7.RELEASE (*)
| +--- org.springframework.security:spring-security-config:5.1.5.RELEASE
| | +--- org.springframework.security:spring-security-core:5.1.5.RELEASE
| | | +--- org.springframework:spring-aop:5.1.6.RELEASE -> 5.1.7.RELEASE (*)
| | | +--- org.springframework:spring-beans:5.1.6.RELEASE -> 5.1.7.RELEASE (*)
| | | +--- org.springframework:spring-context:5.1.6.RELEASE -> 5.1.7.RELEASE (*)
| | | +--- org.springframework:spring-core:5.1.6.RELEASE -> 5.1.7.RELEASE (*)
| | | \--- org.springframework:spring-expression:5.1.6.RELEASE -> 5.1.7.RELEASE (*)
| | +--- org.springframework:spring-aop:5.1.6.RELEASE -> 5.1.7.RELEASE (*)
| | +--- org.springframework:spring-beans:5.1.6.RELEASE -> 5.1.7.RELEASE (*)
| | +--- org.springframework:spring-context:5.1.6.RELEASE -> 5.1.7.RELEASE (*)
| | \--- org.springframework:spring-core:5.1.6.RELEASE -> 5.1.7.RELEASE (*)
| \--- org.springframework.security:spring-security-web:5.1.5.RELEASE
| +--- org.springframework.security:spring-security-core:5.1.5.RELEASE (*)
| +--- org.springframework:spring-aop:5.1.6.RELEASE -> 5.1.7.RELEASE (*)
| +--- org.springframework:spring-beans:5.1.6.RELEASE -> 5.1.7.RELEASE (*)
| +--- org.springframework:spring-context:5.1.6.RELEASE -> 5.1.7.RELEASE (*)
| +--- org.springframework:spring-core:5.1.6.RELEASE -> 5.1.7.RELEASE (*)
| +--- org.springframework:spring-expression:5.1.6.RELEASE -> 5.1.7.RELEASE (*)
| \--- org.springframework:spring-web:5.1.6.RELEASE -> 5.1.7.RELEASE (*)
+--- org.springframework.boot:spring-boot-starter-web -> 2.1.5.RELEASE
| +--- org.springframework.boot:spring-boot-starter:2.1.5.RELEASE (*)
| +--- org.springframework.boot:spring-boot-starter-json:2.1.5.RELEASE
| | +--- org.springframework.boot:spring-boot-starter:2.1.5.RELEASE (*)
| | +--- org.springframework:spring-web:5.1.7.RELEASE (*)
| | +--- com.fasterxml.jackson.core:jackson-databind:2.9.8 (*)
| | +--- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.8
| | | +--- com.fasterxml.jackson.core:jackson-core:2.9.8
| | | \--- com.fasterxml.jackson.core:jackson-databind:2.9.8 (*)
| | +--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.8
| | | +--- com.fasterxml.jackson.core:jackson-annotations:2.9.0
| | | +--- com.fasterxml.jackson.core:jackson-core:2.9.8
| | | \--- com.fasterxml.jackson.core:jackson-databind:2.9.8 (*)
| | \--- com.fasterxml.jackson.module:jackson-module-parameter-names:2.9.8
| | +--- com.fasterxml.jackson.core:jackson-core:2.9.8
| | \--- com.fasterxml.jackson.core:jackson-databind:2.9.8 (*)
| +--- org.hibernate.validator:hibernate-validator:6.0.16.Final (*)
| +--- org.springframework:spring-web:5.1.7.RELEASE (*)
| \--- org.springframework:spring-webmvc:5.1.7.RELEASE
| +--- org.springframework:spring-aop:5.1.7.RELEASE (*)
| +--- org.springframework:spring-beans:5.1.7.RELEASE (*)
| +--- org.springframework:spring-context:5.1.7.RELEASE (*)
| +--- org.springframework:spring-core:5.1.7.RELEASE (*)
| +--- org.springframework:spring-expression:5.1.7.RELEASE (*)
| \--- org.springframework:spring-web:5.1.7.RELEASE (*)
+--- org.springframework.boot:spring-boot-starter-aop -> 2.1.5.RELEASE
| +--- org.springframework.boot:spring-boot-starter:2.1.5.RELEASE (*)
| +--- org.springframework:spring-aop:5.1.7.RELEASE (*)
| \--- org.aspectj:aspectjweaver:1.9.4
+--- org.springframework.cloud:spring-cloud-config-client -> 2.1.1.RELEASE (*)
+--- org.springframework.cloud:spring-cloud-starter-netflix-eureka-client -> 2.1.1.RELEASE
| +--- org.springframework.cloud:spring-cloud-starter:2.1.1.RELEASE
| | +--- org.springframework.boot:spring-boot-starter:2.1.3.RELEASE -> 2.1.5.RELEASE (*)
| | +--- org.springframework.cloud:spring-cloud-context:2.1.1.RELEASE (*)
| | +--- org.springframework.cloud:spring-cloud-commons:2.1.1.RELEASE (*)
| | \--- org.springframework.security:spring-security-rsa:1.0.7.RELEASE
| | \--- org.bouncycastle:bcpkix-jdk15on:1.60
| | \--- org.bouncycastle:bcprov-jdk15on:1.60
| +--- org.springframework.cloud:spring-cloud-netflix-hystrix:2.1.1.RELEASE
| | +--- org.springframework.boot:spring-boot-autoconfigure:2.1.3.RELEASE -> 2.1.5.RELEASE (*)
| | \--- org.springframework.boot:spring-boot-starter-aop:2.1.3.RELEASE -> 2.1.5.RELEASE (*)
| +--- org.springframework.cloud:spring-cloud-netflix-eureka-client:2.1.1.RELEASE
| | \--- org.springframework.cloud:spring-cloud-netflix-hystrix:2.1.1.RELEASE (*)
| +--- com.netflix.eureka:eureka-client:1.9.8
| +--- com.netflix.eureka:eureka-core:1.9.8
| +--- org.springframework.cloud:spring-cloud-starter-netflix-archaius:2.1.1.RELEASE
| | +--- org.springframework.cloud:spring-cloud-starter:2.1.1.RELEASE (*)
| | +--- org.springframework.cloud:spring-cloud-netflix-ribbon:2.1.1.RELEASE
| | | \--- org.springframework.cloud:spring-cloud-netflix-archaius:2.1.1.RELEASE
| | +--- org.springframework.cloud:spring-cloud-netflix-archaius:2.1.1.RELEASE
| | +--- com.netflix.archaius:archaius-core:0.7.6
| | \--- commons-configuration:commons-configuration:1.8
| | \--- commons-lang:commons-lang:2.6
| +--- org.springframework.cloud:spring-cloud-starter-netflix-ribbon:2.1.1.RELEASE
| | +--- org.springframework.cloud:spring-cloud-starter:2.1.1.RELEASE (*)
| | +--- org.springframework.cloud:spring-cloud-netflix-ribbon:2.1.1.RELEASE (*)
| | +--- org.springframework.cloud:spring-cloud-starter-netflix-archaius:2.1.1.RELEASE (*)
| | +--- com.netflix.ribbon:ribbon:2.3.0
| | +--- com.netflix.ribbon:ribbon-core:2.3.0
| | +--- com.netflix.ribbon:ribbon-httpclient:2.3.0
| | +--- com.netflix.ribbon:ribbon-loadbalancer:2.3.0
| | \--- io.reactivex:rxjava:1.2.0
| +--- com.netflix.ribbon:ribbon-eureka:2.3.0
| \--- com.thoughtworks.xstream:xstream:1.4.10
| +--- xmlpull:xmlpull:1.1.3.1
| \--- xpp3:xpp3_min:1.1.4c
+--- org.springframework.cloud:spring-cloud-aws-autoconfigure -> 2.1.1.RELEASE
| +--- org.springframework.cloud:spring-cloud-aws-context:2.1.1.RELEASE
| | +--- org.springframework.cloud:spring-cloud-aws-core:2.1.1.RELEASE
| | | +--- org.springframework:spring-beans:5.1.5.RELEASE -> 5.1.7.RELEASE (*)
| | | +--- org.springframework:spring-aop:5.1.5.RELEASE -> 5.1.7.RELEASE (*)
| | | +--- com.amazonaws:aws-java-sdk-core:1.11.415 (*)
| | | +--- com.amazonaws:aws-java-sdk-s3:1.11.415 (*)
| | | +--- com.amazonaws:aws-java-sdk-ec2:1.11.415
| | | | +--- com.amazonaws:aws-java-sdk-core:1.11.415 (*)
| | | | \--- com.amazonaws:jmespath-java:1.11.415 (*)
| | | +--- com.amazonaws:aws-java-sdk-cloudformation:1.11.415
| | | | +--- com.amazonaws:aws-java-sdk-core:1.11.415 (*)
| | | | \--- com.amazonaws:jmespath-java:1.11.415 (*)
| | | \--- org.slf4j:slf4j-api:1.7.25 -> 1.7.26
| | +--- org.springframework:spring-context:5.1.5.RELEASE -> 5.1.7.RELEASE (*)
| | \--- org.slf4j:slf4j-api:1.7.25 -> 1.7.26
| +--- org.springframework.boot:spring-boot-autoconfigure:2.1.3.RELEASE -> 2.1.5.RELEASE (*)
| \--- org.slf4j:slf4j-api:1.7.25 -> 1.7.26
\--- org.springframework.cloud:spring-cloud-starter-aws -> 2.1.1.RELEASE
+--- org.springframework.cloud:spring-cloud-aws-context:2.1.1.RELEASE (*)
+--- org.springframework.cloud:spring-cloud-aws-autoconfigure:2.1.1.RELEASE (*)
\--- org.slf4j:slf4j-api:1.7.25 -> 1.7.26
This is multi-project and it uses spring and spring-boot simultaneously.
It looks like I have dependencies overlapping from spring and spring boot because some projects use Spring, for example, to build a Rest API and some use Spring Boot for command-line applications.
That happens because you have already spring-cloud-aws-autoconfigure jar on classpath which contains spring.facories which loads automatically AWS related beans (autoconfiguration). When you use in your project annotation #EnableContextInstanceData it underneath causes loading the same configuration second time.

Union of rectangles in a 2d tiled world

I am trying to find the bounding polygon of a set of adjacent cells(row,col) ( convertable to rectangles) in a 2d tiled world.
Processing the cells in a for loop and using the neighbourhood property of the adjacent cells I could eliminate all internal edges and store the rest of the edges.
The edges are stored in std::vector;
Now I need to merge the edges where there is a common vertex and slope is the same.
After merging the edges I need to make the bounding polygon, starting from a vertex going counter clockwise.
Please help to find a method to make it possible.
I think this is a simple algorithm to achieve that.
Consider we have this as input:
| | | | | |
-+---+---+---+---+---+-
| | | | | |
-+---+---+---+---+---+-
| | | a | | |
-+---+---+---+---+---+-
| | b | c | d | |
-+---+---+---+---+---+-
| | | e | | |
-+---+---+---+---+---+-
| | | | | |
Where a, b, c, d, and e are our input tiles stored as a vector of pairs (Coordinates):
std::vector<std::pair<unsigned,unsigned>> tiles;
What we want is this:
| | | | | |
-+---+---+---+---+---+-
| | | | | |
-+---+---*---*---+---+-
| | | | | |
-+---*---* *---*---+-
| | | |
-+---*---* *---*---+-
| | | | | |
-+---+---*---*---+---+-
| | | | | |
The algorithm works as follows:
Build an array of booleans enclosing the entire set of tiles. You have to trasverse the set to find the bounds of that rectangle. Set as true the positions of the array which represent a tile of the set, and as false otherwise.
The output in the example will be (T is true and f is false):
+---+---+---+
| f | T | f |
+---+---+---+
| T | T | T |
+---+---+---+
| f | T | f ]
+---+---+---+
Now you have to traverse the border of the hull polygon. Start at the first element marked as true in the flag array and trasverse the vertices in the same direction until you reach the first vertex again, using this rules:
If the two tiles in front of the current direction/position are false, turn clockwise and add the vertex to the output list (polygon):
(* are vertices added to the polygon, X the current vertex, the arrow the current direction)
+---+---+---+
| f | f | f |
*---+---X---+ --->
| T | T | f |
*---+---+---+
| f | T | f ]
+---+---+---+
goes to
+---+---+---+
| f | f | f | |
*---+---*---+ |
| T | T | f | v
*---+---X---+
| f | T | f ]
+---+---+---+
If one tile is false and one true, go in the same direction (Note that true-false or false-true means you are in a border):
+---+---+---+
| f | f | f | |
*---+---*---+ |
| T | T | f | v
*---+---X---+
| f | T | f ]
+---+---+---+
goes to
+---+---+---+
| f | f | f | |
*---+---*---+ |
| T | T | f | v
*---+---+---+
| f | T | f ]
+---+---X---+
If both tiles are true, turn counter-clockwise and add the vertex to the output list (Note that true-true means you have reached part of the set of tiles, a "wall"):
+---+---+---+
| f | f | f | |
*---+---*---+ |
| T | T | f | v
*---+---X---+
| f | T | T ]
+---+---+---+
goes to
+---+---+---+
| f | f | f |
+---+---*---+
| T | T | f | --->
+---+---*---X
| f | T | T ]
+---+---+---+
Considerations:
tilemap coordinates vs flag-array coordinates
The flag-array represents the rectangle region of the tilemap where the tiles are placed. So the tilemap-coordinates of its first element (tile) is (left,top) where left is the minimum x-coordinate of the selected set of tiles, and top is the minimum y-coordinate of the selected set of tiles.
In the second step of the agorithm, you trasverse the frontier (border) of the set of tiles, using the array as a guide. Note that what you really trasverse is that array, so you have to translate the coordinates from flag-coordinates (logical coordinates) to tilemap-coordinates (physical coordinates) to store the vertices of the polygon. Of course thats easy.
Also note that the algorithm abstract steps trasverse vertices of edges (physical tile coordinates), not logical-coordinates. You have to be sure what "I'm in that vertex" means and what "advance" and "turn" mean in terms of flag-array coordinates.
Border conditions and the front-tiles check
We have defined three rules to advance along the border of the set of tiles. We have used the flag-array as a guide to decide what to do (Advance, turn clockwise, or turn counter-clockwise). Note that when the current vertex is in the border of the array, you could (you should) consider that it have neighbour tiles with a false value.
For example:
+---+---+---+
| f | f | f | |
*---+---*---+ |
| T | T | f | v
*---+---+---+
| f | T | f ]
+---+---X---+
goes to
+---+---+---+
| f | f | f |
*---+---*---+ <--
| T | T | f |
*---+---+---+
| f | T | f ]
+---X---*---+
exactly as if it was this:
+---+---+---+
| f | f | f | |
*---+---*---+ |
| T | T | f | v
*---+---+---+
| f | T | f ]
+---+---X---+
| f | f | f |
*---*---*---+
Possible optimisations
The first step computes the flag array because the algorithm takes the set of tiles selected as a vector. If your tile engine supports it, you could add a property to the tiles (bool selected) and pass the tilemap directly, avoiding the computation and the vertex cooordinates transformations.
Example
Given this flag-array:
+---+---+---+
| T | f | f |
+---+---+---+
| T | T | T |
+---+---+---+
| f | T | T |
+---+---+---+
The execution works as follows (Note that the drawings are the state AFTER the execution of the step):
Find the first true tile. In this case (0,0). So we start at one of its vertex (bottom-left vertex, looking upwards, for example. Note that because its the first true tile, you could use that vertex being sure that it belongs to the polygon. So add that first vertex to the polygon):
Current position: (0,1)
Polygon: {(0,1)}
+---+---+---+ ^
| T | f | f | |
X---+---+---+ |
| T | T | T |
+---+---+---+
| f | T | T |
+---+---+---+
Start the trasverse. In this case, the front tiles are false-true, so advance:
Current position: (0,0)
Polygon: {(0,1)}
X---+---+---+ ^
| T | f | f | |
*---+---+---+ |
| T | T | T |
+---+---+---+
| f | T | T |
+---+---+---+
The front tiles are false-false (We are in a border), so turn clockwise and add the vertex:
Current position: (1,0)
Polygon: {(0,1),(0,0)}
*---X---+---+
| T | f | f |
*---+---+---+
| T | T | T | --->
+---+---+---+
| f | T | T |
+---+---+---+
Now the fron-tiles are false-false (One is out of the array, and the other is false). turn clockwise and add the vertex:
Current position: (1,1)
Polygon: {(0,1),(0,0),(1,0)}
*---*---+---+
| T | f | f | |
*---X---+---+ |
| T | T | T | v
+---+---+---+
| f | T | T |
+---+---+---+
The two front-tiles are true: Turn counter-clockwise and add the vertex:
Current position: (1,2)
Polygon: {(0,1),(0,0),(1,0),(1,1)}
*---*---+---+
| T | f | f |
*---*---X---+
| T | T | T | --->
+---+---+---+
| f | T | T |
+---+---+---+
One tile is false and the other is true: Advance:
Current position: (1,3)
Polygon: {(0,1),(0,0),(1,0),(1,1)}
*---*---+---+
| T | f | f |
*---*---+---X
| T | T | T | --->
+---+---+---+
| f | T | T |
+---+---+---+
Two false tiles (Both out of array): Turn clockwise and add the vertex:
Current position: (2,3)
Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1)}
*---*---+---+
| T | f | f | |
*---*---+---* |
| T | T | T | v
+---+---+---X
| f | T | T |
+---+---+---+
One true and one false(Out of array): Advance:
Current position: (3,3)
Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1)}
*---*---+---+
| T | f | f | |
*---*---+---* |
| T | T | T | v
+---+---+---+
| f | T | T |
+---+---+---X
Two false(Out of array) front-tiles: Turn clockwise and add the vertex:
Current position: (2,3)
Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3)}
*---*---+---+
| T | f | f |
*---*---+---*
| T | T | T | <---
+---+---+---+
| f | T | T |
+---+---X---*
true-false (One true and one out of bounds): Advance:
Current position: (1,3)
Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3)}
*---*---+---+
| T | f | f |
*---*---+---*
| T | T | T | <---
+---+---+---+
| f | T | T |
+---X---+---*
false-false (One false and one out of bounds): Turn clockwise and add the vertex:
Current position: (1,2)
Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3),(1,3)}
*---*---+---+
| T | f | f | ^
*---*---+---* |
| T | T | T | |
+---X---+---+
| f | T | T |
+---*---+---*
true-true front-tiles: Turn counter-clockwise and add the vertex:
Current position: (0,2)
Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3),(1,3),(1,2)}
*---*---+---+
| T | f | f |
*---*---+---*
| T | T | T | <---
X---*---+---+
| f | T | T |
+---*---+---*
false-false front-tiles: Turn clockwise and add the vertex:
Current position: (0,1)
Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3),(1,3),(1,2),(0,2)}
*---*---+---+
| T | f | f | ^
X---*---+---* |
| T | T | T | |
*---*---+---+
| f | T | T |
+---*---+---*
The current vertex is the first vertex of the polygon: The execution have finished. The result is as follows:
Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3),(1,3),(1,2),(0,2)}
*---*
| |
* *-------*
| |
*---* |
| |
*-------*
Because of tiles, this is a 'special case' of finding boundary polygon. I would go with some simple approach.
Tile (x,y) consist of vertices [(x,y), (x+1,y), (x+1,y+1), (x,y+1)]. Vertex is a part of boundary polygon if it is in 1, 2 or 3 tiles. To find vertices on boundary it is enough to count number of tiles it is in. For that it is enough to pass through tiles and increment vertex appearance count for tile 4 vertices. Vertices with tile count 1, 2 or 3 are on the boundary polygon.
To order vertices it is enough to start from some vertex on a boundary and look for a neighbouring vertex that is also on a boundary. To traverse vertices in same direction it is important to take a care of direction order of neighbouring vertices to check. E.g. if last vertex is on -x, than order of directions to check is +y, +x, -y.
Since direction of last edge is known, if next edge is in the same direction than that vertex is for a removal. If region is simple connected, than removal can be known also from tile count. If tile count of a vertex is 2 than vertex is for removal.
For now we don't have guarantee that order is clockwise. That can be check by checking (some of) upper-most edge(s) is it in clockwise direction. If it is not, than reverse polygon.

How to get minimum count rectangles that covers another pile of rectangle?

Assume I have a pile of rectangles, some of which intersect, some isolate. E. g.
+--------------- + +-------- +
| | | |
| | | |
| A | | C |
| +---------------- + | |
| | | | +---------+-------- +
| | | | | |
+---------|----- + B | | D |
| | | |
| | +------------------ +
+---------------- +
+------------------ + +-------- +
| | | |
| E | | X |
+-------------------+ | |
| | +-------- +
| | +------------ +
| | | |
| F | | |
| | | Y |
| | | |
+-------------------+ +------------ +
Rect A, B intersect with each other, C, D have one same point, E, F have two same points, X, Y are isolated.
I have two questions:
How to partion these rectangles into rectangles which cover A, B, C, D, E, F, X, Y exactly also have minimum count like this:
+---------+----- + +-------- +
| | | | |
| | | | |
| | | | |
| | +--------- + | |
| | | | +---------+-------- +
| | | | | |
+---------+ | | | |
| | | | |
| | | +-------------------+
+------+----------+
+------------------ + +-------- +
| | | |
| | | |
| | | |
| | +---------+
| | +------------ +
| | | |
| | | |
| | | |
| | | |
+-------------------+ +-------------+
How to cover intersected rectangles with big ones? Like this:
+---------------------------+ +-------------------+
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | +-------------------+
+---------------------------+
+-------------------+ +---------+
| | | |
| | | |
| | | |
| | +---------+
| | +------------ +
| | | |
| | | |
| | | |
| | | |
+-------------------+ +-------------+
For Q1, I've no idea at all....
For Q2, I wrote some code in C++ but have poor efficiency. I believe there're better methods/algorithm.
bool intersectRect(const Rect& rect1, const Rect& rect2) {
/* if rect1 and rect2 intersect return true
else return false
*/
}
Rect mergeIntersectRects(const set<Rect>& rects) {
// suppose rects are all intersected. This function only return a smallest Rect that cover all rects.
}
set<Rect> mergeRectToRects(const set<Rect>& rectset, const Rect& rect) {
set<Rect> _intersect_rects;
set<Rect> _unintersect_rects;
for(set<Rect>::const_iterator it = rectset.begin();
it != rectset.end();
++it) {
if(intersectRect(*it, rect))
_intersect_rects.insert(*it);
else
_unintersect_rects.insert(*it);
}
if(!_intersect_rects.empty()) {
_intersect_rects.insert(rect);
return mergeRectToRects(_unintersect_rects,
mergeIntersectRects(_intersect_rects));
}
else {
_unintersect_rects.insert(rect);
return _unintersect_rects;
}
}
First, I'm assuming that your rectangles are all axis-aligned.
For Q1, one option would be to sweep the plane while maintaining a list of line segments along the sweep line that lie in the interior of the rectangles. As you discover each rectangle vertex during the sweep you can check to see if it modifies the current interior segments and if so, start or end a rectangle as necessary.
For example, let's say your sweep line moves left to right:
Current
Interior
|
+-|------------- + +-------- + *
| | | | | |
| | | | | |
| | A | | C | |
| | +---------------- + | | |
| | | | | +---------+-------- + |
| | | | | | | |
+-|-------|----- + B | | D | *
| | | | |
| | | +------------------ +
| +---------------- +
|
+-|---------------- + +-------- + *
| | | | | |
| | E | | X | |
| |-----------------+ | | |
| | | +-------- + |
| | | +------------ + |
| | | | | |
| | F | | | |
| | | | Y | |
| | | | | |
+-|-----------------+ +------------ + *
|
When the sweep line is in the position shown above, there are two interior segments. Namely, that inside A and that inside (E U F). When the sweep line reaches the leftmost edge of B, we output a rectangle for the portion of A lying to the left. We then replace the interior of A in the segment list with the interior of (A U B).
Current
Interior
|
+---------+-|--- + +-------- + *
| | | | | | |
| | | | | | |
| | | | | C | |
| | |-------------- + | | |
| | | | | +---------+-------- + |
| | | | | | | |
+---------+ |--- + B | | D | |
| | | | | |
| | | +------------------ + |
+-|-------------- + *
|
+-----------|------ + +-------- + *
| | | | | |
| | | | X | |
| |-------+ | | |
| | | +-------- + |
| | | +------------ + |
| | | | | |
| | | | | |
| | | | Y | |
| | | | | |
+-----------|-------+ +------------ + *
|
For Q2, the answer could be computed during the same sweep by keeping track of the x-coordinate at which a segment was first added to the list (e.g. "left side of A") as well as the min and max y-coordinates that it spans during its lifetime (e.g. bottom of B to top of A). When the segment is finally removed from the list (e.g. "right side of B"), then output a rectangle using these four coordinates.
Sorting the rectangle vertices lexicographically in a preprocessing step would be O(n * log n). Processing them would be O(log n) since you can do a binary search on the known interior ranges. The total runtime should be O(n * log n).
Q1: this is called partition of rectilinear polygon. Answer from Rob's comment has very good description. I found paper mentioned in the answer useful.
Q2: I suppose that you don't want two covers of non-intersecting regions to intersect. Like cover for 3 rectangle, 2 rectangle producing L and rectangle intersection cover of L but not any L rectangle.
If it is like that, than it is possible to incrementally create covers. Here is a simple algorithm for it.
covers = {A}
for each rectangle R
while there is a cover that intersects R, say C
remove C from covers and set R = cover of R and C
add R to covers
This code is not efficient in standard form. With good structure for covers structure, it can be efficient.
Here's the algorithm: http://goo.gl/aWDJo
You can read about finding the convex hull algorithms: http://ralph.cs.cf.ac.uk/papers/Geometry/boxing.pdf
I'd use the method suggested by #Damon but speed up neighbouring rectangle search with some spatial indexing structure, for example a quadtree or a grid. You'd need two of them, first built over the set of input rectangles, to search for intersecting rectangles to split, and second built over the set of split rectangles obtained in first step, to search adjacent rectangles to merge. That should speed things up considerably compared to the naive approach.